简体   繁体   English

如何以编程方式确定SQL Server CE数据库中是否存在表?

[英]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? 有没有办法确定?

UPDATE UPDATE

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();
    }
}

?

UPDATE 2 更新2

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()时得到“ 指定的表已经存在 ”。

UPDATE 3 更新3

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)

UPDATE UPDATE

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();
            }
        }
    }
}

UPDATE 2 更新2

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.

相关问题 如何使用C#确定SQL Server CE表中是否存在列? - How can I determine whether a column exists in a SQL Server CE table with C#? 确定SQL Server CE中是否存在表? - Determine if table exists in SQL Server CE? 如何检查 SQL Server CE 3.5 中是否存在表 - How can I check whether a table exists in SQL Server CE 3.5 如何确定是否存在SQL Server或数据库 - How to determine whether a SQL server or database exists Microsoft SQL Server CE检查表是否存在 - Microsoft SQL Server CE Check if table exists 以编程方式创建SQL Server CE数据库文件 - Create SQL Server CE database file programmatically 如何以编程方式提取SQL Server表架构以构造SQL Server CE? - How to programmatically extract SQL Server table schema to construct SQL Server CE? 如何在C#应用程序的嵌入式SQL Server CE数据库中存储长文本数据? - How can I store long text data in embedded SQL Server CE database of C# application? 如何在Windows Phone上将表添加到已部署的SQL Server CE数据库? - How can I add tables to an already deployed SQL Server CE Database on a Windows Phone? 如何在SQL Server CE数据库上出现“ 80004005文件共享冲突…”错误消息? - How can I circument the “80004005 There is a file sharing violation…” err msg on a SQL Server CE database?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM