2010-09-05 13 views
13

En SQLite, dado este esquema de base deIncremento en un comunicado, en SQLite

CREATE TABLE observations (
    src TEXT, 
    dest TEXT, 
    verb TEXT, 
    occurrences INTEGER 
); 
CREATE UNIQUE INDEX observations_index 
    ON observations (src, dest, verb); 

cada vez que una nueva tupla observación (:src, :dest, :verb) entra, yo quiero ya sea incrementar la columna "ocurrencias" para el vigente fila para esa tupla, o agregue una nueva fila con ocurrencias = 1 si aún no hay una. En concreto pseudocódigo:

if (SELECT COUNT(*) FROM observations 
     WHERE src == :src AND dest == :dest AND verb == :verb) == 1: 
    UPDATE observations SET occurrences = occurrences + 1 
     WHERE src == :src AND dest == :dest AND verb == :verb 
else: 
    INSERT INTO observations VALUES (:src, :dest, :verb, 1) 

Me pregunto si es posible hacer toda esta operación en una declaración SQLite. Eso simplificaría la lógica de la aplicación (que se requiere para ser operaciones de base de datos completamente sincrónicas) y también evitará una búsqueda doble del índice con exactamente la misma clave. INSERTAR O REEMPLAZAR no parece ser lo que quiero, y lamentablemente no hay ACTUALIZACIÓN O INSERCIÓN.

+0

¿No tendría más sentido declarar 'occurrences' como INTEGER? – dan04

+0

D'oh! Quise hacerlo. Editado – zwol

Respuesta

11

Tengo esta respuesta de Igor Tandetnik en sqlite usuarios:

INSERT OR REPLACE INTO observations 
VALUES (:src, :dest, :verb, 
    COALESCE(
    (SELECT occurrences FROM observations 
     WHERE src=:src AND dest=:dest AND verb=:verb), 
    0) + 1); 

Es un poco pero consistentemente más rápido que el enfoque de dan04.

+1

Disculpe si esto es obvio, pero no olvide crear un índice único según el OP o esto siempre creará un nuevo contador y nunca aumentará: 'CREATE UNIQUE INDEX observaciones_index ON observaciones (src, dest, verbo);' . – ahcox

+0

También tenga en cuenta que incrementa el ROWID en cada actualización (porque cada actualización es, en esencia, un DELETE + INSERT) – ayke

3

No sabe de una manera de hacerlo en un comunicado, pero se podría tratar

BEGIN; 
    INSERT OR IGNORE INTO observations VALUES (:src, :dest, :verb, 0); 
    UPDATE observeraions SET occurrences = occurrences + 1 WHERE 
     src = :src AND dest = :dest AND verb = :verb; 
COMMIT; 
Cuestiones relacionadas