111 votes

Comment récupérer le dernier ID auto-incrémenté d'une table SQLite ?

Je possède une table Messages avec les colonnes ID (clé primaire, auto-incrément) et Content (texte).
Je possède une table Utilisateurs avec les colonnes nom d'utilisateur (clé primaire, texte) et Hash.
Un message est envoyé par un Expéditeur (utilisateur) à de nombreux destinataires (utilisateurs) et un destinataire (utilisateur) peut avoir de nombreux messages.
J'ai créé une table Messages_Recipients avec deux colonnes : MessageID (faisant référence à la colonne ID de la table Messages) et Recipient (faisant référence à la colonne nom d'utilisateur dans la table Utilisateurs). Cette table représente la relation de plusieurs à plusieurs entre les destinataires et les messages.

Donc, la question que je me pose est la suivante. L'ID d'un nouveau message sera créé après qu'il a été stocké dans la base de données. Mais comment puis-je conserver une référence à la ligne de Message que je viens d'ajouter afin de récupérer ce nouvel ID de Message?
Je peux toujours chercher dans la base de données la dernière ligne ajoutée bien sûr, mais cela pourrait éventuellement renvoyer une ligne différente dans un environnement multi-threaded?

MODIFIER : Tel que je le comprends pour SQLite, vous pouvez utiliser SELECT last_insert_rowid(). Mais comment puis-je appeler cette instruction depuis ADO.Net?

Mon code de persistence (messages et messagesRecipients sont des 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;//J'espérais que messagerow retiendrait une
    //référence à la nouvelle ligne dans la table Messages, mais ce n'est pas le cas.
    foreach (var recipient in message.Recipients)
    {
        var row = messagesRecipients.NewMessages_RecipientsRow();
        row.Recipient = recipient;
        //row.MessageID= Comment le trouver ??
        messagesRecipients.AddMessages_RecipientsRow(row);
        UpdateMessagesRecipients();//méthode non affichée
    } 

}

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

0voto

beeline09 Points 1

Ma solution est que, dans une transaction, nous insérons des données et demandons immédiatement la valeur maximale du champ CLÉ PRIMAIRE.

Voici mon exemple. DayliForecast.sq:

import kotlin.Int;

CREATE TABLE IF NOT EXISTS DailyForecast (
    pid             INTEGER PRIMARY KEY AUTOINCREMENT DEFAULT NULL,
    year            INTEGER AS Int  NOT NULL,
    month           INTEGER AS Int  NOT NULL,
    day_of_month    INTEGER AS Int  NOT NULL,
    hours_of_sun    REAL            NOT NULL DEFAULT 0,
    forecast_key    TEXT            NOT NULL
);

CREATE UNIQUE INDEX IF NOT EXISTS DailyForecastDate ON DailyForecast (
    year            DESC,
    month           DESC,
    day_of_month    DESC,
    forecast_key    DESC
);

insert:
REPLACE INTO DailyForecast
    VALUES (?,?,?,?,?,?);

lastPid:
SELECT MAX(pid) FROM DailyForecast;

selectByDateRange:
SELECT * FROM DailyForecast
    WHERE
        forecast_key = ?
        AND year >= ?
        AND month >= ?
        AND day_of_month >= ?
        AND year <= ?
        AND month <= ?
        AND day_of_month <= ? LIMIT 5;

ForecastDbRepositoryImpl:

class ForecastDbRepositoryImpl(private val database: Database): ForecastDbRepository() {

    override suspend fun insertDailyForecast(dailyForecast: DailyForecast): Long {
        return database.transactionWithResult {
            insertForecast(dailyForecast)
        }
    }

    override suspend fun insertDailyForecast(dailyForecasts: List<DailyForecast>): List<Long> {
        return database.transactionWithResult {
            dailyForecasts.map { insertForecast(it) }
        }
    }

    private fun insertForecast(dailyForecast: DailyForecast): Long {
        database.dayliForecastQueries.insert(
            pid = dailyForecast.pid.takeIf { it >= 0L },
            year = dailyForecast.year,
            month = dailyForecast.month,
            day_of_month = dailyForecast.day_of_month,
            hours_of_sun = dailyForecast.hours_of_sun,
            forecast_key = dailyForecast.forecast_key
        )
        return database.dayliForecastQueries.lastPid().executeAsOne().MAX ?: 0L
    }
}

J'ai testé cela moi-même et cela fonctionne très bien!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X