如何在SQLite中检查表是否存在?

时间:2009-10-21 14:22:10

标签: sqlite

如何,可靠,检查SQLite,是否存在特定的用户表?

我不是要求不可靠的方法,例如检查表上的“select *”是否返回错误(这是一个好主意吗?)。

原因是这样的:

在我的程序中,我需要创建并填充一些表,如果它们不存在的话。

如果它们确实存在,我需要更新一些表格。

我是否应该使用其他路径来表示已经创建了相关表格 - 例如,通过在磁盘上的程序初始化/设置文件中创建/放置/设置某个标志或什么?

或者我的方法有意义吗?

25 个答案:

答案 0 :(得分:930)

我错过了常见问题解答条目。

无论如何,为了将来参考,完整的查询是:

SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}';

其中{table_name}是要检查的表的名称。

文档部分供参考:Database File Format. 2.6. Storage Of The SQL Database Schema

答案 1 :(得分:515)

如果您使用的是SQLite版本3.3+,则可以轻松地创建一个表格:

create table if not exists TableName (col1 typ1, ..., colN typN)

以同样的方式,您可以使用以下内容删除表:

drop table if exists TableName

答案 2 :(得分:164)

变体是使用SELECT COUNT(*)而不是SELECT NAME,即

SELECT count(*) FROM sqlite_master WHERE type='table' AND name='table_name';

如果表不存在,则返回0,否则返回1。这可能对您的编程很有用,因为数字结果更快/更容易处理。下面说明如何使用SQLiteDatabase,Cursor,带参数的rawQuery在Android中执行此操作。

boolean tableExists(SQLiteDatabase db, String tableName)
{
    if (tableName == null || db == null || !db.isOpen())
    {
        return false;
    }
    Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM sqlite_master WHERE type = ? AND name = ?", new String[] {"table", tableName});
    if (!cursor.moveToFirst())
    {
        cursor.close();
        return false;
    }
    int count = cursor.getInt(0);
    cursor.close();
    return count > 0;
}

答案 3 :(得分:39)

你可以尝试:

SELECT name FROM sqlite_master WHERE name='table_name'

答案 4 :(得分:33)

如果您收到“表已存在”错误,请在SQL字符串中进行如下更改:

FileStream

这样可以避免例外情况。

答案 5 :(得分:32)

SQLite表名称不区分大小写,但默认情况下比较区分大小写。要在所有情况下都能正常运行,您需要添加COLLATE NOCASE

SELECT name FROM sqlite_master WHERE type='table' AND name='table_name' COLLATE NOCASE

答案 6 :(得分:31)

使用:

PRAGMA table_info(your_table_name)

如果结果表为空,则your_table_name不存在。

文档:

  

PRAGMA schema.table_info(table-name);

     

此pragma为指定表中的每列返回一行。结果集中的列包括列名,数据类型,列是否可以为NULL以及列的默认值。 " pk"对于不属于主键的列,结果集中的列为零,并且是主键中作为主键一部分的列的列的索引。

     

table_info pragma中指定的表也可以是视图。

示例输出:

cid|name|type|notnull|dflt_value|pk
0|id|INTEGER|0||1
1|json|JSON|0||0
2|name|TEXT|0||0

答案 7 :(得分:29)

请参阅this

SELECT name FROM sqlite_master
WHERE type='table'
ORDER BY name;

答案 8 :(得分:22)

如果您使用fmdb,我认为您只需导入FMDatabaseAdditions 并使用bool功能:

[yourfmdbDatabase tableExists:tableName].

答案 9 :(得分:13)

如果表存在,则以下代码返回1;如果表不存在,则返回0。

SELECT CASE WHEN tbl_name = "name" THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = "name" AND type = "table"

答案 10 :(得分:10)

请注意,要检查TEMP数据库中是否存在表,您必须使用sqlite_temp_master而不是sqlite_master

SELECT name FROM sqlite_temp_master WHERE type='table' AND name='table_name';

答案 11 :(得分:8)

这是我使用的功能:

给定SQLDatabase Object = db

public boolean exists(String table) {
    try {
         db.query("SELECT * FROM " + table);
         return true;
    } catch (SQLException e) {
         return false;
    }
}

答案 12 :(得分:7)

使用此代码:

SELECT name FROM sqlite_master WHERE type='table' AND name='yourTableName';

如果返回的数组计数等于1,则表示该表存在。否则它就不存在了。

答案 13 :(得分:3)

使用

SELECT 1 FROM table LIMIT 1;

以防止读取所有记录。

答案 14 :(得分:3)

使用最新的sqlite-net-pcl nuget软件包(1.5.231)(使用SQLite 3),我现在在C#中找到的最可靠的方法如下:

var result = database.GetTableInfo(tableName);
if ((result == null) || (result.Count == 0))
{
    database.CreateTable<T>(CreateFlags.AllImplicit);
}

答案 15 :(得分:1)

在我看来,使用简单的SELECT查询非常可靠。最重要的是它可以在许多不同的数据库类型(SQLite / MySQL)中检查表的存在。

SELECT 1 FROM table;

当您可以使用其他可靠机制来确定查询是否成功时(例如,您通过Qt中的QSqlQuery查询数据库),这是有意义的。

答案 16 :(得分:1)

您可以编写以下查询来检查表是否存在。

SELECT name FROM sqlite_master WHERE name='table_name'

“ table_name”是您创建的表名。例如

 CREATE TABLE IF NOT EXISTS country(country_id INTEGER PRIMARY KEY AUTOINCREMENT, country_code TEXT, country_name TEXT)"

并检查

  SELECT name FROM sqlite_master WHERE name='country'

答案 17 :(得分:1)

您也可以使用 db metadata 来检查表是否存在。

namespace PX.Objects.AP
{
  public class APReleaseProcess_Extension : PXGraphExtension<APReleaseProcess>
  {
  public delegate List<APRegister> ReleaseDocProcDel(JournalEntry je, ref APRegister doc, PXResult<APInvoice, 
                                                    CurrencyInfo, Terms, Vendor> res, bool isPrebooking, 
                                                    out List<INRegister> inDocs);
  [PXOverride]
  public List<APRegister> ReleaseDocProc(JournalEntry je, ref APRegister doc, 
                                        PXResult<APInvoice, CurrencyInfo, Terms, Vendor> res, 
                                        bool isPrebooking, 
                                        out List<INRegister> inDocs, ReleaseDocProcDel del)
  {
      je.RowInserting.AddHandler<GLTran>((sender, e) =>
      {
          GLTran glTran = e.Row as GLTran;
          APTran apTran = PXResult<APTran>.Current;
          if (glTran != null && apTran != null)
          {
              APTranExt apTranEx = PXCache<APTran>.GetExtension<APTranExt>(apTran);
              if (apTran != null && apTranEx.UsrJobOrderNbr != null)
              {
                  GLTranExt glTranEx = PXCache<GLTran>.GetExtension<GLTranExt>(glTran);
                  glTranEx.UsrJobOrderNbr = apTranEx.UsrJobOrderNbr;
              }
          }

          //APInvoice apInv = PXResult<APInvoice>.Current;
          APInvoice apInv = PXSelect<APInvoice,
                                Where<APInvoice.refNbr, Equal<Required<GLTran.refNbr>>,
                                    And<APInvoice.docType,
                                        Equal<Required<GLTran.tranType>>>>>.Select(sender.Graph, glTran.RefNbr, glTran.TranType);

          if (glTran != null && apInv != null)
          {
              GLTranExt glTranEx = PXCache<GLTran>.GetExtension<GLTranExt>(glTran);
              glTranEx.UsrInvoiceNbr = apInv.InvoiceNbr;
          }

          APTaxTran apTaxTran = PXResult<APTaxTran>.Current;
          if (glTran != null && apTaxTran != null)
          {
              APTaxTranExt apTaxTranEx = PXCache<APTaxTran>.GetExtension<APTaxTranExt>(apTaxTran);
              if (apTaxTran != null && apTaxTranEx != null)
              {
                  GLTranExt glTranEx = PXCache<GLTran>.GetExtension<GLTranExt>(glTran);
                  glTranEx.UsrNoSeriFaktur = apTaxTranEx.UsrNoSeriFaktur;
                 }

              }

          }
              );
          return del(je, ref doc, res, isPrebooking, out inDocs);
      }
  }
}

答案 18 :(得分:1)

c ++函数检查db和所有附加数据库中是否存在表和(可选)列。

bool exists(sqlite3 *db, string tbl, string col="1")
{
    sqlite3_stmt *stmt;
    bool b = sqlite3_prepare_v2(db, ("select "+col+" from "+tbl).c_str(),
    -1, &stmt, 0) == SQLITE_OK;
    sqlite3_finalize(stmt);
    return b;
}

答案 19 :(得分:0)

如果您使用 python 文件运行它并且显然使用 sqlite3。打开命令提示符或 bash 使用任何东西

  1. python3 file_name.py 首先在其中编写您的 sql 代码。
  2. 然后运行 ​​sqlite3 file_name.db
  3. .table 此命令将给出存在的表。

答案 20 :(得分:0)

我的首选方法:

SELECT "name" FROM pragma_table_info("table_name") LIMIT 1;

如果得到一行结果,则表存在。这比使用 sqlite_master 检查更好(对我而言),因为它还会检查附加数据库和临时数据库。

答案 21 :(得分:0)

表是否迅速存在于数据库中

func tableExists(_ tableName:String) -> Bool {
        sqlStatement = "SELECT name FROM sqlite_master WHERE type='table' AND name='\(tableName)'"
        if sqlite3_prepare_v2(database, sqlStatement,-1, &compiledStatement, nil) == SQLITE_OK {
            if sqlite3_step(compiledStatement) == SQLITE_ROW {
                return true
            }
            else {
                return false
            }
        }
        else {
            return false
        }
            sqlite3_finalize(compiledStatement)
    }

答案 22 :(得分:0)

class CPhoenixDatabase():
    def __init__(self, dbname):
        self.dbname = dbname
        self.conn = sqlite3.connect(dbname)

    def is_table(self, table_name):
        """ This method seems to be working now"""
        query = "SELECT name from sqlite_master WHERE type='table' AND name='{" + table_name + "}';"
        cursor = self.conn.execute(query)
        result = cursor.fetchone()
        if result == None:
            return False
        else:
            return True

注意:这现在在我的Mac上使用Python 3.7.1的情况下

答案 23 :(得分:0)

我以为我会把这2美分放在这个讨论中,即使它是相当陈旧的。 如果表存在则此查询返回标量1,否则返回0。

select 
    case when exists 
        (select 1 from sqlite_master WHERE type='table' and name = 'your_table') 
        then 1 
        else 0 
    end as TableExists

答案 24 :(得分:0)

这是我的SQLite Cordova代码:

get_columnNames('LastUpdate', function (data) {
    if (data.length > 0) { // In data you also have columnNames
        console.log("Table full");
    }
    else {
        console.log("Table empty");
    }
});

另一个:

function get_columnNames(tableName, callback) {
    myDb.transaction(function (transaction) {
        var query_exec = "SELECT name, sql FROM sqlite_master WHERE type='table' AND name ='" + tableName + "'";
        transaction.executeSql(query_exec, [], function (tx, results) {
            var columnNames = [];
            var len = results.rows.length;
            if (len>0){
                var columnParts = results.rows.item(0).sql.replace(/^[^\(]+\(([^\)]+)\)/g, '$1').split(','); ///// RegEx
                for (i in columnParts) {
                    if (typeof columnParts[i] === 'string')
                        columnNames.push(columnParts[i].split(" ")[0]);
                };
                callback(columnNames);
            }
            else callback(columnNames);
        });
    });
}