테이블이 존재하는지 SQLite를 어떻게 확인합니까?


893

특정 사용자 테이블이 있는지 SQLite에서 확실하게 체크인 하는 방법은 무엇입니까?

테이블의 "select *"가 오류를 반환했는지 여부를 확인하는 것과 같은 신뢰할 수없는 방법을 요구하지 않습니다 (이것은 좋은 생각입니까?).

이유는 다음과 같습니다.

내 프로그램에서 일부 테이블이 존재하지 않으면 테이블을 작성하고 채워야합니다.

이미 존재하는 경우 일부 테이블을 업데이트해야합니다.

문제의 테이블이 이미 생성되었다는 신호를 보내려면 다른 경로를 사용해야합니까?

아니면 내 접근 방식이 의미가 있습니까?


선택에 테이블이 존재하지 않으면 SQLite에서 예외가 발생합니다. 더 멋진 작업이 필요하지 않습니다.
— NoChance

34
@NoChance 그것은하지만 다른 많은 것들도 마찬가지입니다. 마치 눈을 감고 앞으로 나아갈 때 나무가 실제로 있는지 확인하는 것과 약간 같습니다.)
— randomsock

@randomsock, 좋은 예이지만, 차가 내 차라면 특별히 무섭다 ...
— NoChance

@randomsock, 나는 sqlite 규칙이 무엇인지 모르지만 허가보다 용서를 구하는 것은 더 비판적입니다. 즉, 조건을 사용하는 대신 예외를 잡습니다.
— Eric

1
@Eric 현재로서는 질문에 파이썬이 포함되어 있지 않지만 오류가 발생했다고 가정하면 오류는 일반적 sqlite3.OperationalError이므로 오류 메시지를 구문 분석하여 예를 들어 "table TABLE_NAME already exists"메시지인지 확인해야합니다. 그렇지 않은 경우 오류를 제거하고 오류 문구가 변경되지 않을 것이라고 보장하지는 않습니다.
— Markus von Broady

답변:


1021

나는 그 FAQ 항목을 놓쳤다.

어쨌든 나중에 참조 할 수 있도록 전체 쿼리는 다음과 같습니다.

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

{table_name}확인할 테이블 이름은 어디에 있습니까 ?

참조를위한 설명서 섹션 : 데이터베이스 파일 형식. 2.6. SQL 데이터베이스 스키마의 저장

  • 지정된 이름의 테이블 목록이 반환됩니다. 즉, 커서는 0의 카운트 (존재하지 않음) 또는 1의 카운트 (존재 함)를 갖습니다.

7
다음 중이 시스템 테이블을 다루는 SQLite 설명서는 무엇입니까?
— Pawel Veselov

29
@Pawel Veselov : "SQLite 데이터베이스의 파일 형식"섹션 : sqlite.org/fileformat2.html
— Bryan Oakley

14
그러나 TEMP 테이블에서는 작동하지 않습니다. TEMP 테이블은 "sqlite_temp_master"에 있습니다.
— PatchyFog

11
이것은 부울을 반환합니까? 테이블이 존재하거나 존재하지 않으면 무엇을 반환합니까?
— Dagrooms 2016 년

8
@Dagrooms 이름이 지정된 테이블 목록을 반환합니다. 즉, 커서는 0 (존재하지 않음) 또는 1 (존재)의 개수를 갖습니다.
— Rein S

555

SQLite 버전 3.3 이상을 사용하는 경우 다음을 사용하여 테이블을 쉽게 만들 수 있습니다.

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

같은 방법으로 다음을 사용하여 테이블이 존재하는 경우에만 테이블을 제거 할 수 있습니다.

drop table if exists TableName

3
점을 유의 create table문이 불완전 (테이블 컬럼 사양 누락)된다.
— Eric Platon

11
인덱스에 대한 유사한 구조도 있습니다 : 하지 TABLENAME (COL1)에 TableName_col1를 존재하는 경우 인덱스를 생성
— lowtech

26
이것은 정답이 아니어야하지만 질문이 다르게 표현 된 경우입니다. OP는 테이블을 삭제하거나 생성하기 전에 테이블을 확인하는 방법을 묻지 않았습니다. 존재하지 않는 테이블을 쿼리해야하는 경우 어떻게합니까? 이것이 제가 지금 당면한 문제이며,이 대답은이 일반적인 문제 설명에서 가장 잘 작동합니다. 이것은 좋은 빠른 대안입니다.
— Dagrooms 2016 년

@ 회의실, 당신이 옳을 수도 있습니다. OP가 요청하지 않았지만이 답변을 찾고있었습니다. :)
— earik87

169

변형은 SELECT NAME 대신 SELECT COUNT (*)를 사용하는 것입니다.

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

33
"SELECT 1"이 훨씬 빠를 것이라고 생각합니다.
— PatchyFog

cursor.getInt (0)이 데이터베이스의 레코드 수와 같은 이유는 무엇입니까?
— Semyon Danilov

1
우리는 TABLE이 sqlite 스키마에 나타나는 횟수를 세고 있습니다. 카운트 0은 테이블이 존재하지 않음을 의미합니다. 카운트 1은 테이블이 존재 함을 의미합니다. 이것들은 count의 예상되는 두 가지 값입니다.
— Stephen Quan

1
(from COUNT(*)) 숫자 는 처리하기 쉽지만 행의 존재 여부를 반환하는 것이 더 쉽습니다. 행이 있으면 행이 있고 행이 없으면 행이없는 것입니다. (이미 moveToFirst에서 이미 실패를 확인 했으므로 해당 시점에서 작업이 완료됩니다.)
— dash-tom-bang

false를 반환하기 전에 커서를 닫으려면 코드를 업데이트하십시오.
— Dave Thomas

43

시도해 볼 수 있습니다 :

SELECT name FROM sqlite_master WHERE name='table_name'

4
유용한 상점을 입력 = 표는 것
— mafu

C #을 사용한다면,이 명령을 사용하지 마십시오 SQLiteReader reader = cmd.ExecuteReader();과을 dt.Load(reader)(여기서 dtA는 DataTable). 테이블을 찾을 수없는 경우이 Object reference is not an instance of an object예외를 .Load()발견했습니다. 대신를 사용 SQLiteDataAdapter adapter = new SQLiteDataAdapter(cmd); 하고 할 adapter.Fill(ds)여기서 dsA는 DataSet. 그렇다면 ds.Tables.Count > 0그리고 return ds.Tables[0];만약 그렇다면 (또는 else return null) 볼 수 있습니다 . 그럼 당신은 그것을 확인할 수 DataTable있는위한 null경우 dt.Rows != null, 그리고 경우dt.Rows.Count>0
— vapcguy

34

사용하다:

PRAGMA table_info(your_table_name)

결과 테이블이 비어 있으면 your_table_name존재하지 않습니다.

선적 서류 비치:

PRAGMA schema.table_info (테이블 이름);

이 pragma는 명명 된 테이블의 각 열에 대해 하나의 행을 반환합니다. 결과 집합의 열에는 열 이름, 데이터 형식, 열이 NULL 일 수 있는지 여부 및 열의 기본값이 포함됩니다. 기본 키의 일부가 아닌 열의 경우 결과 집합의 "pk"열이 0이고 기본 키의 일부인 열의 기본 키 열의 인덱스입니다.

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

이것은 테이블이 파이썬에 존재하는지 확인하는 좋은 방법입니다.
— Michael Murphy

또는 Xamarin Forms
— SerenityNow

4
프로그래밍 방식으로 열 정의를 얻는 좋은 방법입니다.
— w00t

33

SQLite 테이블 이름은 대소 문자를 구분하지 않지만 비교는 기본적으로 대소 문자를 구분합니다. 모든 경우에이 작업을 제대로 수행하려면 추가해야합니다 COLLATE NOCASE.

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

33

"테이블이 이미 존재합니다"오류가 발생하면 다음과 같이 SQL 문자열을 변경하십시오.

CREATE table IF NOT EXISTS table_name (para1,para2);

이런 식으로 예외를 피할 수 있습니다.



23

당신이 사용하는 경우 fmdb을 , 나는 당신이 단지 수 있다고 생각 FMDatabaseAdditions을 가져 와 부울 함수를 사용

[yourfmdbDatabase tableExists:tableName].

1
이 방법을 사용하려면 "FMDatabaseAdditions.h"를 가져와야합니다. 그렇지 않으면 왜 제거했는지 궁금 할 것입니다. :)
— 윌

이것이 정답 일 수 있지만 질문은 특정 언어의 특정 라이브러리가 아닌 sqlite에 관한 것입니다. 답은 라이브러리의 메소드 중 하나를 호출하는 것이 아니라 SQL 코드를 제공하는 것이어야한다고 생각합니다.
— nacho4d

13

다음 코드는 테이블이 있으면 1을 반환하고 테이블이 없으면 0을 반환합니다.

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

1
where 조건이 결과를 막기 때문에 테이블이 존재하지 않으면 여전히 아무것도 반환하지 않습니다.
— David Gausmann

10

TEMP 데이터베이스에 테이블이 있는지 확인하려면 다음 sqlite_temp_master대신 사용해야 합니다 sqlite_master.

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

9

내가 사용한 기능은 다음과 같습니다.

주어진 SQLDatabase 오브젝트 = db

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

1
나는 슬프게도 내 안드로이드 앱에서 이것을 사용해야했습니다. 삼성 장치가 다른 모든 사람들과 작업하는 표준 sqlite_master 테이블 구조를 사용하지 않는다는 것을 알았습니다.
— Anthony Chuinard 2016 년

7

이 코드를 사용하십시오 :

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

반환 된 배열 개수가 1이면 테이블이 존재한다는 의미입니다. 그렇지 않으면 존재하지 않습니다.


4
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

참고 : 이것은 현재 Python 3.7.1이 설치된 Mac에서 작동합니다.


이것은 다른 모든 답변보다 더 깨끗해 보입니다 .. 감사합니다 !!
— Harsha Vardhan

나를 위해 작동하지 않습니다 : table_name 주위의 {} 괄호를 지워야합니다.
— 바나나

1
확인 table_name(사용자 입력 등) untrused 소스로부터 제공되지 않는, 그렇지 않으면 그것은 SQL 인젝션에 취약 할 것입니다. 텍스트 조작 기술 대신 매개 변수를 사용하는 것이 좋습니다.
— astef

3

사용하다

SELECT 1 FROM table LIMIT 1;

모든 레코드를 읽을 수 없도록합니다.


테이블이 존재하지만 레코드가없는 경우 NULL을 리턴합니다.
— radiospiel

테이블이 존재하지 않으면 오류가 발생합니다. 그것을 잡아라, 당신은 그것이 존재하지 않는다는 것을 안다.
— luckydonald

흐름 제어로 오류 처리를 사용하는 것은 일반적으로 모범 사례로 간주되지 않습니다. 이것은 아마도 피해야합니다.
— Jeff Woodard

3

다음 쿼리를 작성하여 테이블 존재를 확인할 수 있습니다.

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'

6
이것은 9 년 전의 이미 승인 된 인기 답변과 어떻게 다릅니 까?
— 케빈 반 다이크

3

SQLite 3을 사용하는 최신 sqlite-net-pcl nuget 패키지 (1.5.231)를 사용하여 지금 C #에서 찾은 가장 신뢰할 수있는 방법은 다음과 같습니다.

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

2

내 생각에 간단한 SELECT 쿼리를 사용하는 것이 매우 안정적입니다. 무엇보다도 많은 다른 데이터베이스 유형 (SQLite / MySQL)에서 테이블 존재를 확인할 수 있습니다.

SELECT 1 FROM table;

쿼리의 성공 여부를 결정하기 위해 신뢰할 수있는 다른 메커니즘을 사용할 수있는 경우에 적합합니다 (예 : Qt의 QSqlQuery를 통해 데이터베이스를 쿼리하는 경우 ).


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

편집 : 최근에 sqlite3_table_column_metadata 함수를 발견했습니다. 그 후

bool exists(sqlite3* db,const char *tbl,const char *col=0)
{return sqlite3_table_column_metadata(db,0,tbl,col,0,0,0,0,0)==SQLITE_OK;}

공용 정적 부울 tableExists (SQLiteDatabase 데이터베이스, 문자열 tableName) {return database.rawQuery ( "sq에서 이름 선택 sqlite_master WHERE type = 'table'AND name = '"+ tableName + "'", null) .moveToFirst (); }
— nick

문자열 연결이 모든 결과를 낳을 수 있으므로 매우 비효율적이고 위험한 방법입니다.
— Andrea Moro

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

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

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)
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.