SQLite 테이블에서 마지막 자동 증가 ID를 검색하는 방법은 무엇입니까?


82

열 ID (기본 키, 자동 증가) 및 콘텐츠 (텍스트)가있는 테이블 메시지가 있습니다.
사용자 이름 (기본 키, 텍스트) 및 해시 열이있는 테이블 사용자가 있습니다.
한 발신자 (사용자)가 여러 수신자 (사용자)에게 메시지를 보내고 수신자 (사용자)는 여러 메시지를 가질 수 있습니다.
MessageID (MessageID (Messages 테이블의 ID 열 참조) 및 Recipient (Users 테이블의 사용자 이름 열 참조)) 열이있는 Messages_Recipients 테이블을 생성했습니다.이 테이블은 수신자와 메시지 간의 다 대다 관계를 나타냅니다.

그래서 제가 가진 질문은 이것입니다. 새 메시지의 ID는 데이터베이스에 저장된 후 생성됩니다. 그러나이 새 MessageID를 검색하기 위해 방금 추가 한 MessageRow에 대한 참조를 어떻게 보유 할 수 있습니까?
물론 마지막으로 추가 된 행을 데이터베이스에서 항상 검색 할 수 있지만 다중 스레드 환경에서 다른 행을 반환 할 수 있습니까?

편집 : SQLite에 대해 이해하면 SELECT last_insert_rowid(). 그러나 ADO.Net에서이 문을 어떻게 호출합니까?

내 지속성 코드 (messages 및 messagesRecipients는 DataTables) :

public void Persist(Message message)
{
    pm_databaseDataSet.MessagesRow messagerow;
    messagerow=messages.AddMessagesRow(message.Sender,
                            message.TimeSent.ToFileTime(),
                            message.Content,
                            message.TimeCreated.ToFileTime());
    UpdateMessages();
    var x = messagerow;//I hoped the messagerow would hold a
    //reference to the new row in the Messages table, but it does not.
    foreach (var recipient in message.Recipients)
    {
        var row = messagesRecipients.NewMessages_RecipientsRow();
        row.Recipient = recipient;
        //row.MessageID= How do I find this??
        messagesRecipients.AddMessages_RecipientsRow(row);
        UpdateMessagesRecipients();//method not shown
    } 

}

private void UpdateMessages()
{
    messagesAdapter.Update(messages);
    messagesAdapter.Fill(messages);
}

SQlite (ADO.Net 버전)를 사용합니다.
Dabblernl

답변:


88

SQL Server를 사용하면 현재 프로세스에 대한 마지막 ID 값을 가져 오기 위해 SCOPE_IDENTITY ()를 선택합니다.

SQlite를 사용하면 자동 증분처럼 보입니다.

SELECT last_insert_rowid()

삽입 직후.

http://www.mail-archive.com/sqlite-users@sqlite.org/msg09429.html

이 값을 얻으려면 귀하의 의견에 대한 답변으로 다음과 같은 SQL 또는 OleDb 코드를 사용하고 싶을 것입니다.

using (SqlConnection conn = new SqlConnection(connString))
{
    string sql = "SELECT last_insert_rowid()";
    SqlCommand cmd = new SqlCommand(sql, conn);
    conn.Open();
    int lastID = (Int32) cmd.ExecuteScalar();
}

2
다시 감사합니다! 불행히도 DataTable을 업데이트하는 데 사용되는 연결이 닫히기 전에 last_insert_rowid () 함수를 호출해야하므로 작동하지 않습니다. 이것은 SQLite의
특이한

1
미안하지만 사실 일 것입니다. messagesAdapter.Update (messages); 후에 실행을 시도 했습니까?
MikeW

2
@Dabblernl은 다른 답변이 더 신뢰할 수있는 것 같습니다. 다른 답변이 더 도움이된다고 생각되면 수락 된 답변을 변경하고 싶을 수 있습니다.
MikeW

그러나 RowId가 항상 PRIMARY KEY와 같은 것은 아닙니다. 제외시켰다If the table has a column of type INTEGER PRIMARY KEY then that column is another alias for the rowid.
Кое Кто에게

110

또 다른 옵션은 시스템 테이블을 보는 것 sqlite_sequence입니다. 자동 증가 기본 키로 테이블을 생성하면 sqlite 데이터베이스에 자동으로 해당 테이블이 있습니다. 이 테이블은 sqlite가 autoincrement 필드를 추적하여 일부 행을 삭제하거나 일부 삽입이 실패한 후에도 기본 키를 반복하지 않도록하기위한 것입니다 (여기 http://www.sqlite.org/autoinc .html ).

따라서이 테이블을 사용하면 다른 항목을 삽입 한 후에도 새로 삽입 된 항목의 기본 키를 찾을 수 있다는 추가 이점이 있습니다 (물론 다른 테이블에서!). 삽입이 성공했는지 확인한 후 (그렇지 않으면 거짓 번호가 표시됨) 다음을 수행하면됩니다.

select seq from sqlite_sequence where name="table_name"

1
시퀀스가 증가하고 행이 삭제 된 후에 작동합니다.
Marek Bar

좋은 대답입니다. 이상하게도 "SQLite 용 DB 브라우저"에서 "sqlite_sequence"에서 행을 제거하면 일부 테이블에 대한 마지막 ID를 더 이상 얻지 못할 것입니다.
CoolMind

8

SELECT last_insert_rowid()다중 스레드 환경에서 사용 하는 데 문제가 있습니다. 다른 스레드가 autoinc가있는 다른 테이블에 삽입하면 last_insert_rowid가 새 테이블에서 autoinc 값을 반환합니다.

여기에 그들이 doco에서 말하는 곳이 있습니다.

sqlite3_last_insert_rowid () 함수가 실행되는 동안 별도의 스레드가 동일한 데이터베이스 연결에서 새 INSERT를 수행하여 마지막 삽입 rowid를 변경하는 경우 sqlite3_last_insert_rowid ()에서 반환 된 값은 예측할 수 없으며 이전 또는 새 마지막과 같지 않을 수 있습니다. rowid를 삽입하십시오.

sqlite.org doco 에서 가져온 것입니다.


1
각 스레드에 대해 별도의 연결을 사용할 수 있다고 생각하지만 성능에 큰 영향을 미치는 것으로 나타났습니다. 내 시나리오에서는 초당 약 15 개의 삽입 만 수행 할 수 있습니다.
Fidel

내 생각에는 별도의 스레드가 동일한 문제가 될 것입니다. 불행히도 현재까지 스레드로부터 안전한 작업이없는 것 같습니다. 내 직감은 여러 트랜잭션으로도 충분하지 않을 것이므로주의해야합니다.
rogerdpack

5

@polyglot 솔루션의 샘플 코드

SQLiteCommand sql_cmd;
sql_cmd.CommandText = "select seq from sqlite_sequence where name='myTable'; ";
int newId = Convert.ToInt32( sql_cmd.ExecuteScalar( ) );

4

Android Sqlite 에 따르면 마지막 삽입 행 ID 가 또 다른 쿼리가 있습니다.

SELECT rowid from your_table_name order by ROWID DESC limit 1

1
이 옵션은 rowid를 찾기 전에 정렬 알고리즘을 실행하여 성능이 저하됩니다
Sr. Libre

2
덜 최적 일 수도 있지만 연결이 닫히고 다시 열리면 실제로 작동하고 다른 두 솔루션은 나에게 적합하지 않습니다.
Francine DeGrood Taylor 19

다음 변형은 ORDER BY. 더 빨라야하지만 테스트하지는 않았습니다.SELECT MAX(rowid) FROM your_table_name
tanius
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.