web-dev-qa-db-ja.com

SQLiteテーブルから最後の自動インクリメントIDを取得する方法は?

列ID(プライマリキー、自動インクリメント)およびコンテンツ(テキスト)のテーブルメッセージがあります。
ユーザー名(プライマリキー、テキスト)とハッシュの列を持つテーブルユーザーがあります。
1人の送信者(ユーザー)から多くの受信者(ユーザー)にメッセージが送信され、受信者(ユーザー)は多くのメッセージを持つことができます。
2つの列を持つテーブルMessages_Recipientsを作成しました。MessageID(MessagesテーブルのID列を参照)とRecipient(Usersテーブルのユーザー名列を参照)。メッセージ。

だから、私が持っている質問はこれです。新しいメッセージのIDは、データベースに保存された後に作成されます。しかし、この新しいMessageIDを取得するために、追加したばかりのMessageRowへの参照をどのように保持できますか?
もちろん、追加された最後の行をデータベースでいつでも検索できますが、マルチスレッド環境で異なる行を返す可能性はありますか?

編集:私がSQLiteのためにそれを理解するように、あなたはSELECT last_insert_rowid()を使うことができます。しかし、ADO.Netからこのステートメントをどのように呼び出すのでしょうか?

私の永続化コード(メッセージと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);
}
70
Dabblernl

SQL Serverでは、SELECT SCOPE_IDENTITY()を使用して、現在のプロセスの最後のID値を取得します。

SQliteを使用すると、自動インクリメントを実行するように見えます

SELECT last_insert_rowid()

挿入直後。

http://www.mail-archive.com/[email protected]/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();
}
72
MikeW

もう1つのオプションは、システムテーブルsqlite_sequence。自動インクリメントの主キーを持つテーブルを作成した場合、sqliteデータベースにはそのテーブルが自動的に作成されます。このテーブルは、sqliteが自動インクリメントフィールドを追跡し、一部の行を削除した後、または一部の挿入が失敗した後でもプライマリキーを繰り返さないようにするためのものです(詳細については、こちらを参照してください http://www.sqlite .org/autoinc.html )。

したがって、このテーブルを使用すると、他のテーブルに(もちろん他のテー​​ブルに)何かを挿入した後でも、新しく挿入したアイテムのプライマリキーを見つけることができるという利点があります。挿入が成功したことを確認した後(そうでない場合は、偽の番号を取得します)、次の手順を実行するだけです。

select seq from sqlite_sequence where name="table_name"
100
polyglot

マルチスレッド環境でSELECT last_insert_rowid()を使用すると問題が発生しました。 autoincを持つ別のテーブルに別のスレッドが挿入されると、last_insert_rowidは新しいテーブルからautoinc値を返します。

彼らがドコでそれを述べる場所は次のとおりです:

Sqlite3_last_insert_rowid()関数の実行中に別のスレッドが同じデータベース接続で新しいINSERTを実行し、したがって最後の挿入ROWIDを変更すると、sqlite3_last_insert_rowid()によって返される値は予測不能で、古いまたは新しい最後のいずれとも等しくない可能性がありますROWIDを挿入します。

sqlite.org doco からです

8
Fidel

@polyglotソリューションのサンプルコード

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

Android Sqlite get last insert row id 別のクエリがあります:

SELECT rowid from your_table_name order by ROWID DESC limit 1
2
CoolMind