테이블이 존재하는지 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.