Comment insérer des lignes sélectionnées de table_source
à table_target
en utilisant SQL dans MySQL où:
id
Le INSERT INTO table_target SELECT * FROM table_source
trivial échoue sur les entrées en double pour la clé primaire.
Soit vous listez tous les champs souhaités dans l'insertion ... sélectionnez, soit vous utilisez autre chose en externe pour créer la liste pour vous.
SQL n'a pas quelque chose comme SELECT * except somefield FROM
, vous devrez donc mordre la balle et écrire les noms de champs.
Les noms de colonnes doivent être spécifiés -
INSERT INTO table_target SELECT NULL, column_name1, column_name2, column_name3, ...
FROM table_source;
Il suffit de passer NULL comme valeur pour le champ ID d’incrémentation automatique.
Fastidieux mais sûr et correct.
L'écriture d'instructions INSERT sans fournir de liste de colonnes conduit à un code difficile à déboguer et, plus important encore, à un code très fragile qui se cassera si la définition de la table est modifiée.
Si vous ne pouvez absolument pas écrire vous-même les noms des colonnes, il est relativement facile de créer dans votre code un outil qui créera pour vous la liste séparée par des virgules.
Bien entendu, la clé primaire doit être unique. Cela dépend de ce que vous voulez atteindre, mais vous pouvez exclure des lignes avec une clé primaire déjà existante.
INSERT INTO table_target SELECT * FROM table_source
WHERE table_source.id NOT IN (SELECT id FROM table_target)
UPDATE: étant donné que vous avez également besoin des lignes supplémentaires, vous devez d'abord résoudre le conflit. Est-ce que table_source a des relations? Sinon, vous pouvez changer ces clés:
UPDATE table_source SET id = id + 1000
WHERE id IN (SELECT id FROM table_target)
Où 1000, est une constante, assez grande pour qu'ils disparaissent à la fin de votre table.
Je pense que vous pourriez utiliser une syntaxe comme celle-ci:
INSCRIRE AU tableau (a, b, c) VALEURS (1,2,3) ON DUPLICATE KEY UPDATE c = c + 1;
REF: http://dev.mysql.com/doc/refman/5.0/fr/insert-on-duplicate.html J'espère que cela vous aidera
Ceci est ma solution finale à la mise à jour en masse avec la commande 'replace insert'.
SET @@session.group_concat_max_len = @@global.max_allowed_packet;
SET @schema_db = 'db';
SET @tabl = 'table';
SET @cols = (SELECT CONCAT('`',GROUP_CONCAT(COLUMN_NAME SEPARATOR '`, `'), '`') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema_db AND TABLE_NAME = @tabl GROUP BY TABLE_NAME);
SET @Querystr = CONCAT('REPLACE INTO ',@schema_db,'.',@tabl,' SELECT ', @cols,' FROM import.tbl_', @tabl);
PREPARE stmt FROM @Querystr;
EXECUTE stmt;
Il semble que les colonnes ne puissent pas être placées dans une instruction préparée MySQL. J'ai compilé la solution suivante pour le test:
SET @schema_db = 'DB';
SET @table = 'table';
SET @cols = (SELECT CONCAT(GROUP_CONCAT(COLUMN_NAME SEPARATOR ', '), "\n") FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @schema_db AND TABLE_NAME = @table GROUP BY TABLE_NAME);
SET @Querystr = CONCAT('SELECT',' ', @cols,' ','FROM',' ',@schema_db,'.',@table,' ', 'Limit 5');
PREPARE stmt FROM @Querystr;
EXECUTE stmt;
INSERT IGNORE
juste "contourner" les lignes en double.
Vous pouvez probablement le faire avec des déclarations préparées.
PREPARE table_target_insert FROM 'INSERT INTO table_target SELECT ? FROM table_source';
SET @cols:='';
SELECT @cols:=GROUP_CONCAT(IF(column_name = 'id','NULL',column_name) separator ",") FROM information_schema.columns WHERE table_name='table_source';
EXECUTE table_target_insert USING @cols;