如何检查Access数据库表中特定列是否存在

3

我想知道如何检查在 Access 数据库的特定表(例如:myTable)中是否存在特定列(例如:日期)。

我已经阅读了 这个答案,其中提供了一个查询,结果是另一个查询。

IF NOT EXISTS(SELECT * 
              FROM sys.columns 
              WHERE [name] = N'columnName' 
                AND [object_id] = OBJECT_ID(N'tableName'))
BEGIN
    ALTER TABLE ADD COLUMN MYCOLUMN
END

但我需要的是一个 true/false 结果。

更新 1

我该如何在我的 C# 应用程序中实现这一点?

也许可以使用 SqlCommand.ExecuteScalar() 或其他方法吗?


@marc_s 我使用 ExecuteScalarExecuteNonQuery 时遇到了 无效的 SQL 语句;预期为 'DELETE'、'INSERT'、'PROCEDURE'、'SELECT' 或 'UPDATE'。 错误。 - Ghasem
这里有一个关于如何从C#中确定Access中是否存在表格的答案。也许它会指引你比SQL Server代码更有帮助的方向:https://dev59.com/7lPTa4cB1Zd3GeqPlrR7#4793675 - Shannon Severance
1
是的,您在最初的问题中没有提到这是针对 MS Access 的...... SqlCommand 和这个 T-SQL 代码只适用于 SQL Server..... - marc_s
6个回答

3

正如Andre451在其答案中提到的那样,您可以使用Access DAO来检查相关TableDef对象的Fields集合,如下所示:

// test data
string dbFileSpec = @"C:\Users\Public\Database1.accdb";
string tblName = "Clients";
string colName = "LastName";

// COM reference required for project:
// Microsoft Office 14.0 Access Database Engine Object Library
//
var dbe = new Microsoft.Office.Interop.Access.Dao.DBEngine();
Microsoft.Office.Interop.Access.Dao.Database db = dbe.OpenDatabase(dbFileSpec);
Microsoft.Office.Interop.Access.Dao.TableDef tbd = db.TableDefs[tblName];
bool colExists = false;
foreach (Microsoft.Office.Interop.Access.Dao.Field fld in tbd.Fields)
{
    if (fld.Name.Equals(colName, StringComparison.InvariantCultureIgnoreCase))
    {
        colExists = true;
        break;
    }
}
db.Close();

Console.WriteLine("Column " + (colExists ? "exists" : "does not exist"));

3
感谢所有提供解决方案的人,我整合了一些答案,得出了自己的解决方案。也许这不是最好的解决方案,但至少我不需要添加额外的dll到引用中或处理Access不支持的存储过程。
OleDbConnection con = new OleDbConnection("my database address");
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT TOP 1 date FROM myTable";
con.Open();
bool exists = true;
try
{
  var x = cmd.ExecuteScalar();
}
catch (Exception e)
{
  exists = false;
}
con.Close();

2

试试这个:

BEGIN

IF NOT EXISTS(SELECT * FROM sys.columns 
        WHERE [name] = N'columnName' AND [object_id] = OBJECT_ID(N'tableName'))
SELECT 0
ELSE
SELECT 1 
END

在C#中使用:

SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "StoredProcedure3";
con.Open();
var x = cmd.ExecuteScalar();
MessageBox.Show(x.ToString());
con.Close();

不使用存储过程的方法:

SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "IF NOT EXISTS(SELECT * FROM sys.columns WHERE [name] = N'columnName' AND [object_id] = OBJECT_ID(N'tableName')) SELECT 0 ELSE SELECT 1 ";
con.Open();
var x = (int)cmd.ExecuteScalar();
MessageBox.Show(x.ToString());
con.Close();

我该如何在 c# 中实现它? - Ghasem
你为什么要使用.ExecuteScalar()?这个SQL根本不返回任何数据 - 应该使用.ExecuteNonQuery() - marc_s
1
为什么不行?它会返回01 - Salah Akbari
我使用 ExecuteScalarExecuteNonQuery 时遇到了 无效的 SQL 语句;期望 'DELETE'、'INSERT'、'PROCEDURE'、'SELECT' 或 'UPDATE'。 错误。 - Ghasem
2
SQL Server的代码无法在MS Access数据库中运行。 - Shannon Severance
显示剩余4条评论

2
如果有人将来需要此方法,以下是我在我的Access数据库上使用的方法。
void CheckTableFields(OleDbConnection con)
{
    var table = "Company";
    var field = "Location";
    var sSQL = $"SELECT TOP 1 * FROM [{table}]";

    using (OleDbConnection con = new OleDbConnection("MsJetOledbConnectionString"))
    {
        con.Open();
        using (var cmd = new OleDbCommand(sSQL, con))
        {
            try
            {
                DataTable dtGen = new DataTable();
                dtGen.Load(cmd.ExecuteReader());

                System.Data.DataColumnCollection columns = dtGen.Columns;

                if (!columns.Contains(field))
                {
                    //Field NOT found - add new 'Location2' column
                    cmd.CommandText = $"ALTER TABLE [{table}] ADD COLUMN {field} TEXT(50)";
                    var result = cmd.ExecuteNonQuery();

                    WriteLine($"{DateTime.Now}:   Table Column {{{field}}} added successfully");
                }
                else
                {
                    WriteLine($"{DateTime.Now}:   Table Column {{{field}}}  already exists");
                }
            }
            catch (Exception ex)
            {
                WriteLine($"[DataService.CheckCompanyTableFields]  Error - {{{ex.Message}}}");
            }
        }
    }
}

除了最后一行,它运行得非常完美。我删除了false。 WriteLine($"[DataService.CheckCompanyTableFields] Error - {{{ex.Message}}}", false); - Shane.A

1
在Access VBA中,您可以使用TableDef.Fields集合。不知道您是否可以从C#中使用这些对象。
为什么不直接执行以下伪代码?
columnExists = True
try
    ExecuteSql "SELECT TOP 1 [Date] FROM myTable"
catch
    // Error: column doesn't exist
    columnExists = False

1
编程出错?为什么我觉得这不可接受。 - webs
如果没有.Exists方法,而替代方案是循环遍历所有字段,我认为这是完全可以接受的。 - Andre

0

通过简单的方式:

select true

完整代码:

IF NOT EXISTS(SELECT * FROM sys.columns 
        WHERE [name] = N'columnName' AND [object_id] = OBJECT_ID(N'tableName'))
    BEGIN
        select true
    END

ELSE

    BEGIN
        select false
    END

我该如何在 c# 中实现它? - Ghasem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接