J'ai 2 tables (srcTable1 et destTable) qui ont des schémas identiques. J'essaie de copier toutes les lignes de srcTable vers destTable et d'ignorer les doublons. Je pensais pouvoir ajouter une clause WHERE à une sous-requête qui ne me donnerait que les lignes qui ne sont pas des doublons Cependant, cela ne semble pas fonctionner. Je ne reçois aucune ligne insérée ou sélectionnée.
INSERT INTO destTable
SELECT * FROM srcTable
WHERE NOT EXISTS(SELECT * FROM destTable)
Je réalise que je pourrais faire quelque chose comme ça:
INSERT INTO destTable
SELECT * FROM srcTable
WHERE MyKey IN (SELECT MyKey FROM destTable)
Cependant, mes tables ont plusieurs clés et je ne vois pas comment vous pouvez le faire avec plusieurs clés.
Une idée de ce que je fais mal ou avez-vous de meilleures idées?
Votre problème est que vous avez besoin d'une autre clause where dans la sous-requête qui identifie ce qui fait un doublon:
INSERT INTO destTable
SELECT Field1,Field2,Field3,...
FROM srcTable
WHERE NOT EXISTS(SELECT *
FROM destTable
WHERE (srcTable.Field1=destTable.Field1 and
SrcTable.Field2=DestTable.Field2...etc.)
)
Comme l'a noté un autre intervenant, une jointure externe est probablement une approche plus concise. Mon exemple ci-dessus était juste une tentative d'expliquer en utilisant votre requête actuelle pour être plus compréhensible. L'une ou l'autre approche pourrait fonctionner techniquement.
INSERT INTO destTable
SELECT s.field1,s.field2,s.field3,...
FROM srcTable s
LEFT JOIN destTable d ON (d.Key1 = s.Key1 AND d.Key2 = s.Key2 AND...)
WHERE d.Key1 IS NULL
Les deux approches ci-dessus supposent que vous ne souhaitez pas insérer de lignes de la source qui sont peut-être déjà dans la destination. Si vous êtes plutôt préoccupé par la possibilité que la source ait des lignes en double, essayez quelque chose comme ça.
INSERT INTO destTable
SELECT Distinct field1,field2,field3,...
FROM srcTable
Une dernière chose. Je vous suggérerais également de répertorier les champs spécifiques de votre instruction insert au lieu d'utiliser SELECT *.
Je me rends compte que c'est vieux, mais je suis arrivé ici de Google et après avoir examiné la réponse acceptée, j'ai rédigé ma propre déclaration et cela a fonctionné pour moi, j'espère que quelqu'un la trouvera utile:
INSERT IGNORE INTO destTable SELECT id, field2,field3... FROM origTable
Edit: Cela fonctionne sur MySQL Je n'ai pas testé sur MSSQL
J'espère que cette requête vous aidera
INSERT INTO `dTable` (`field1`, `field2`)
SELECT field1, field2 FROM `sTable`
WHERE `sTable`.`field1` NOT IN (SELECT `field1` FROM `dTable`)
Quelque chose comme ça?:
INSERT INTO destTable
SELECT s.* FROM srcTable s
LEFT JOIN destTable d ON d.Key1 = s.Key1 AND d.Key2 = s.Key2 AND...
WHERE d.Key1 IS NULL
Avez-vous essayé SELECT DISTINCT?
INSERT INTO destTable
SELECT DISTINCT * FROM srcTable
insert into tbl2
select field1,field2,... from tbl1
where not exists
(
select field1,field2,...
from person2
where (tbl1.field1=tbl2.field1 and
tbl1.field2=tbl2.field2 and .....)
)
Avez-vous essayé d’abord de supprimer les doublons dans la sous-requête?
INSERT INTO destTable
SELECT source.* FROM(
SELECT *
FROM srcTable
EXCEPT
SELECT src.* FROM
srcTable AS src
INNER JOIN destTable AS dest
/* put in below line the conditions to match repeated registers */
ON dest.SOME_FANCY_MATCH = src.SOME_FANCY_MATCH AND ...
) as source
Si les ensembles sont très grands, ce n’est peut-être pas la meilleure solution.
La solution qui a fonctionné pour moi avec PHP/PDO.
public function createTrainingDatabase($p_iRecordnr){
// Methode: Create an database envirioment for a student by copying the original
// @parameter: $p_iRecordNumber, type:integer, scope:local
// @var: $this->sPdoQuery, type:string, scope:member
// @var: $bSuccess, type:boolean, scope:local
// @var: $aTables, type:array, scope:local
// @var: $iUsernumber, type:integer, scope:local
// @var: $sNewDBName, type:string, scope:local
// @var: $iIndex, type:integer, scope:local
// -- Create first the name of the new database --
$aStudentcard = $this->fetchUsercardByRecordnr($p_iRecordnr);
$iUserNumber = $aStudentcard[0][3];
$sNewDBName = $_SESSION['DB_name']."_".$iUserNumber;
// -- Then create the new database --
$this->sPdoQuery = "CREATE DATABASE `".$sNewDBName."`;";
$this->PdoSqlReturnTrue();
// -- Create an array with the tables you want to be copied --
$aTables = array('1eTablename','2ndTablename','3thTablename');
// -- Populate the database --
for ($iIndex = 0; $iIndex < count($aTables); $iIndex++)
{
// -- Create the table --
$this->sPdoQuery = "CREATE TABLE `".$sNewDBName."`.`".$aTables[$iIndex]."` LIKE `".$_SESSION['DB_name']."`.`".$aTables[$iIndex]."`;";
$bSuccess = $this->PdoSqlReturnTrue();
if(!$bSuccess ){echo("Could not create table: ".$aTables[$iIndex]."<BR>");}
else{echo("Created the table ".$aTables[$iIndex]."<BR>");}
// -- Fill the table --
$this->sPdoQuery = "REPLACE `".$sNewDBName."`.`".$aTables[$iIndex]."` SELECT * FROM `".$_SESSION['DB_name']."`.`".$aTables[$iIndex]."`";
$bSuccess = $this->PdoSqlReturnTrue();
if(!$bSuccess ){echo("Could not fill table: ".$aTables[$iIndex]."<BR>");}
else{echo("Filled table ".$aTables[$index]."<BR>");}
}
}
DISTINCT est le mot clé que vous recherchez.
Dans MSSQL, la copie de lignes uniques d'une table à une autre peut se faire comme suit:
SELECT DISTINCT column_name
INTO newTable
FROM srcTable
Le column_name
est la colonne à partir de laquelle vous recherchez les valeurs uniques.
Testé et fonctionne.