[英]How can I programmatically determine if a table exists within a SQL Server CE database?
Back when I only had one table in my .sdf
file, this code worked fine: 回到我的
.sdf
文件中只有一个表时,这段代码运行正常:
const string sdfPath = @"\Program Files\duckbilled\Platypus.sdf";
string dataSource = string.Format("Data Source={0}", sdfPath);
if (!File.Exists(sdfPath))
{
using (var engine = new SqlCeEngine(dataSource))
{
engine.CreateDatabase();
}
using (var connection = new SqlCeConnection(dataSource))
{
connection.Open();
using (var command = new SqlCeCommand())
{
command.Connection = connection;
command.CommandText =
"CREATE TABLE Platydudes (Id int NOT NULL, BillSize smallint NOT NULL, Description nvarchar(255)";
command.ExecuteNonQuery();
}
}
}
...but now I need to know, not whether the database file ( Platypus.sdf
) exists, but whether a particular table (such as Platydudes
) exists in that table/file. ...但现在我需要知道,不是数据库文件(
Platypus.sdf
)是否存在,而是该表/文件中是否存在特定的表 (例如Platydudes
)。 Is there a way to determine that? 有没有办法确定?
The 'IF NOT EXISTS' clause in the query causes a runtime exception. 查询中的“IF NOT EXISTS”子句导致运行时异常。 This code:
这段代码:
using (var connection = new SqlCeConnection(dataSource))
{
connection.Open();
using (var command = new SqlCeCommand())
{
command.Connection = connection;
command.CommandText = "IF NOT EXISTS( SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'InventoryItems') " +
"CREATE TABLE InventoryItems (Id nvarchar(50) NOT NULL, PackSize smallint NOT NULL, Description nvarchar(255), DeptDotSubdept numeric, UnitCost numeric, UnitList numeric, UPCCode nvarchar(50), UPCPackSize smallint, CRVId int);";
command.ExecuteNonQuery();
}
}
...causes this exception to be thrown: There was an error parsing the query. ...导致抛出此异常: 解析查询时出错。 [ Token line number = 1, Token line offset = 1, Token in error = IF ]
[令牌行号= 1,令牌行偏移= 1,令牌错误= IF]
So obviously the "IF" business is unwanted by the query parser. 显然,查询解析器不需要“IF”业务。 Is there another way to only create the table if it doesn't already exist?
是否有另一种方法只创建表,如果它还不存在? Or should I, each time, first delete the table then recreate it?
或者我应该每次首先删除表格然后重新创建它? IOW, should I do this:
我应该这样做:
using (var connection = new SqlCeConnection(dataSource))
{
connection.Open();
using (var command = new SqlCeCommand())
{
command.Connection = connection;
command.CommandText = "DELETE InventoryItems";
command.ExecuteNonQuery();
}
using (var command = new SqlCeCommand())
{
command.Connection = connection;
command.CommandText = "CREATE TABLE InventoryItems (Id nvarchar(50) NOT NULL, PackSize smallint NOT NULL, Description nvarchar(255), DeptDotSubdept numeric, UnitCost numeric, UnitList numeric, UPCCode nvarchar(50), UPCPackSize smallint, CRVId int);";
command.ExecuteNonQuery();
}
}
? ?
To answer my question above in the first update: NOPE! 在第一次更新中回答我上面的问题:NOPE! If I do that, I get " The specified table already exists " on the second call to .ExecuteNonQuery().
如果我这样做,我会在第二次调用.ExecuteNonQuery()时得到“ 指定的表已经存在 ”。
In response to Shiva's comment to my answer: 回应湿婆对我的回答的评论:
This (reusing the command object) fails the same way ("table already exists"): 这(重用命令对象)失败的方式相同(“表已存在”):
using (var command = new SqlCeCommand())
{
command.Connection = connection;
command.CommandText = "DELETE InventoryItems";
command.ExecuteNonQuery();
command.CommandText = "CREATE TABLE InventoryItems (Id nvarchar(50) NOT NULL, PackSize smallint NOT NULL, Description nvarchar(255), DeptDotSubdept numeric, UnitCost numeric, UnitList numeric, UPCCode nvarchar(50), UPCPackSize smallint, CRVId int);";
command.ExecuteNonQuery();
}
SQL Compact doesn't like much for logic inside a SQL statement, so Shiva's answer probably won't pass the parser. SQL Compact对SQL语句中的逻辑不太喜欢,因此Shiva的答案可能不会通过解析器。 He's on the right course, though.
不过,他是在正确的路线上。 You can to do it in two steps:
您可以分两步完成:
Here's the TableExists
method from the SQL Compact implementation of the OpenNETCF ORM : 这是OpenNETCF ORM的SQL Compact实现中的
TableExists
方法:
public override bool TableExists(string tableName)
{
var connection = GetConnection(true);
try
{
using (var command = GetNewCommandObject())
{
command.Transaction = CurrentTransaction as SqlCeTransaction;
command.Connection = connection;
var sql = string.Format(
"SELECT COUNT(*) FROM information_schema.tables WHERE table_name = '{0}'",
tableName);
command.CommandText = sql;
var count = Convert.ToInt32(command.ExecuteScalar());
return (count > 0);
}
}
finally
{
DoneWithConnection(connection, true);
}
}
Obviously it's not complete for your case, but it's pretty easy to understand. 很明显,你的情况并不完整,但它很容易理解。
CurrentTransaction
could easily be null. CurrentTransaction
很容易为空。 GetNewCommandObject
simply returns a new SqlCeCommand
instance. GetNewCommandObject
只返回一个新的SqlCeCommand
实例。 GetConnection
simply could return a new SqlCeConnection
instance. GetConnection
只是可以返回一个新的SqlCeConnection
实例。 DoneWithConnection could be a NOP. DoneWithConnection可能是NOP。 Basiocally these are all handling the fact that the ORM supports a plethora of backing stores.
基本上这些都是处理ORM支持过多支持商店的事实。 The kernel of info you need is the SQL that I pass in and how I determine the true/false return.
您需要的信息内核是我传入的SQL以及我如何确定true / false返回。
My (untested in a compiler) guess to the resulting method would be something like this: 我(在编译器中未经测试)猜测结果方法将是这样的:
public bool TableExists(SqlCeConnection connection, string tableName)
{
using (var command = new SqlCeCommand())
{
command.Connection = connection;
var sql = string.Format(
"SELECT COUNT(*) FROM information_schema.tables WHERE table_name = '{0}'",
tableName);
command.CommandText = sql;
var count = Convert.ToInt32(command.ExecuteScalar());
return (count > 0);
}
}
Using Database helper: 使用数据库助手:
var db = Database.Open("MyDatabase");
var sql = @"SELECT Count(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'MyTable'"
var count = db.QueryValue(sql);
if(count.Equals(1)){
//table exists
}
If you want check if a Table exist you must use TABLE_SCHEMA
如果要检查表是否存在,则必须使用
TABLE_SCHEMA
IF (EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'TheSchema'
AND TABLE_NAME = 'TheTable'))
BEGIN
--Do Stuff
END
Based on Shiva's answer, I will do something like this: 根据Shiva的回答,我会做这样的事情:
if (!File.Exists(sdfPath))
{
using (var engine = new SqlCeEngine(dataSource))
{
engine.CreateDatabase();
}
}
using (var connection = new SqlCeConnection(dataSource))
{
connection.Open();
using (var command = new SqlCeCommand())
{
command.Connection = connection;
command.CommandText ="IF NOT EXISTS( SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Platydudes') "
+ "CREATE TABLE Platydudes (Id int NOT NULL, BillSize smallint NOT NULL, Description nvarchar(255) )";
command.ExecuteNonQuery();
}
}
...repeating "using (var connection = ..." sections as needed for each table (Platypups, Platypops, &c) ...根据需要为每个表重复“使用(var connection = ...”部分(Platypups,Platypops,&c)
Using ctacke's code, I now have this: 使用ctacke的代码,我现在有了这个:
public static void ConditionallyCreateTables()
{
const string sdfPath = @"\Program Files\duckbilled\Platypus.sdf";
string dataSource = string.Format("Data Source={0}", sdfPath);
if (!File.Exists(sdfPath))
{
using (var engine = new SqlCeEngine(dataSource))
{
engine.CreateDatabase();
}
}
using (var connection = new SqlCeConnection(dataSource))
{
connection.Open();
using (var command = new SqlCeCommand())
{
command.Connection = connection;
if (!TableExists(connection, "InventoryItems"))
{
command.CommandText = "CREATE TABLE InventoryItems (Id nvarchar(50) NOT NULL, PackSize smallint NOT NULL, Description nvarchar(255), DeptDotSubdept numeric, UnitCost numeric, UnitList numeric, UPCCode nvarchar(50), UPCPackSize smallint, CRVId int);";
command.ExecuteNonQuery();
}
if (!TableExists(connection, "Departments"))
{
command.CommandText = "CREATE TABLE Departments (Id int NOT NULL, DeptNum int NOT NULL, DepartmentName nvarchar(255))";
command.ExecuteNonQuery();
}
if (!TableExists(connection, "Subdepartments"))
{
command.CommandText = "CREATE TABLE Subdepartments (Id int NOT NULL, DeptId int NOT NULL, SubdeptId int NOT NULL, DepartmentName nvarchar(255))";
command.ExecuteNonQuery();
}
if (!TableExists(connection, "Redemptions"))
{
command.CommandText = "CREATE TABLE Redemptions (Id int NOT NULL, RedemptionId nvarchar(50), RedemptionItemId nvarchar(50), RedemptionName nvarchar(255), RedemptionAmount numeric, RedemptionDept nvarchar(50), RedemptionSubdept nvarchar(50))";
command.ExecuteNonQuery();
}
}
}
}
I have now changed it to this format: 我现在已将其更改为以下格式:
if (TableExists(connection, "InventoryItems"))
{
command.CommandText = "DROP TABLE InventoryItems";
command.ExecuteNonQuery();
}
command.CommandText = "CREATE TABLE InventoryItems (Id nvarchar(50) NOT NULL, PackSize smallint NOT NULL, Description nvarchar(255), DeptDotSubdept float, UnitCost float, UnitList float, UPCCode nvarchar(50), UPCPackSize smallint, CRVId int);";
command.ExecuteNonQuery();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.