MySQL Conditional Insert

Sto attraversando un momento difficile formando un INSERT condizionale

Ho x_table con colonne (istanza, utente, articolo) dove ID di istanza è unico. Voglio inserire una nuova riga solo se l’utente non ha già un determinato articolo.

Ad esempio, cercando di inserire istanza = 919191 user = 123 item = 456

Insert into x_table (instance, user, item) values (919191, 123, 456) ONLY IF there are no rows where user=123 and item=456 

Qualsiasi aiuto o guida nella giusta direzione sarebbe molto apprezzato.

    Se il DBMS non impone limitazioni su quale tabella selezionare quando si esegue un inserimento, provare:

     INSERT INTO x_table(instance, user, item) SELECT 919191, 123, 456 FROM dual WHERE NOT EXISTS (SELECT * FROM x_table WHERE user = 123 AND item = 456) 

    In questo, dual è una tabella con una sola riga (trovata originariamente in Oracle, ora anche altrove). La logica è che l’istruzione SELECT genera una singola riga di dati con i valori richiesti, ma solo quando i valori non sono già stati trovati.

    In alternativa, guarda la dichiarazione MERGE.

    Puoi anche usare INSERT IGNORE che ignora silenziosamente l’inserto invece di aggiornare o inserire una riga quando hai un indice univoco su (utente, elemento).

    La query sarà simile a questa:

     INSERT IGNORE INTO x_table(instance, user, item) VALUES (919191, 123, 456) 

    È ansible aggiungere l’indice univoco con CREATE UNIQUE INDEX user_item ON x_table (user, item) .

    Hai mai provato qualcosa del genere?

     INSERT INTO x_table SELECT 919191 as instance, 123 as user, 456 as item FROM x_table WHERE (user=123 and item=456) HAVING COUNT(*) = 0; 

    Con UNIQUE(user, item) , fai:

     Insert into x_table (instance, user, item) values (919191, 123, 456) ON DUPLICATE KEY UPDATE user=123 

    l’ user=123 bit è un “no-op” per far corrispondere la syntax della clausola ON DUPLICATE senza effettivamente fare nulla quando ci sono duplicati.

    Nel caso in cui non si voglia impostare un vincolo univoco, questo funziona come un incantesimo:

     INSERT INTO `table` (`column1`, `column2`) SELECT 'value1', 'value2' FROM `table` WHERE `column1` = 'value1' AND `column2` = 'value2' HAVING COUNT(`column1`) = 0 

    Spero che sia d’aiuto !

    Se aggiungi un vincolo che (x_table.user, x_table.item) è univoco, allora l’inserimento di un’altra riga con lo stesso utente e l’object fallirà.

    per esempio:

     mysql> create table x_table ( instance integer primary key auto_increment, user integer, item integer, unique (user, item)); Query OK, 0 rows affected (0.00 sec) mysql> insert into x_table (user, item) values (1,2),(3,4); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> insert into x_table (user, item) values (1,6); Query OK, 1 row affected (0.00 sec) mysql> insert into x_table (user, item) values (1,2); ERROR 1062 (23000): Duplicate entry '1-2' for key 2 

    Sebbene sia opportuno controllare la duplicazione prima di inserire i dati, suggerisco di inserire un vincolo / indice univoco sulle colonne in modo che non possano essere inseriti per errore dati duplicati.

    Quello che vuoi è INSERT INTO table (...) SELECT ... WHERE ... dal manuale di MySQL 5.6 .

    Nel tuo caso è:

     INSERT INTO x_table (instance, user, item) SELECT 919191, 123, 456 WHERE (SELECT COUNT(*) FROM x_table WHERE user=123 AND item=456) = 0 

    O forse dal momento che non stai usando alcuna logica complicata per determinare se eseguire INSERT o no, puoi semplicemente impostare un tasto UNIQUE sulla combinazione di queste due colonne e quindi utilizzare INSERT IGNORE .

     Insert into x_table (instance, user, item) values (919191, 123, 456) where ((select count(*) from x_table where user=123 and item=456) = 0); 

    La syntax può variare in base al tuo DB …

    Leggera modifica della risposta di Alex, puoi anche solo fare riferimento al valore della colonna esistente:

     Insert into x_table (instance, user, item) values (919191, 123, 456) ON DUPLICATE KEY UPDATE user=user 

    Quindi questo rappresenta PostgreSQL

     INSERT INTO x_table SELECT NewRow.* FROM (SELECT 919191 as instance, 123 as user, 456 as item) AS NewRow LEFT JOIN x_table ON x_table.user = NewRow.user AND x_table.item = NewRow.item WHERE x_table.instance IS NULL 

    È ansible utilizzare la seguente soluzione per risolvere il problema:

     INSERT INTO x_table(instance, user, item) SELECT 919191, 123, 456 FROM dual WHERE 123 NOT IN (SELECT user FROM x_table)