2010-08-26 7 views
1

J'utilise la déclarationcommande merge dans SQL Server

insert into target 
select * from source 
where [set of conditions] for a while. 

trouvé récemment cette commande MERGE qui sera plus efficace d'utiliser mon but pour que je puisse changer la déclaration ci-dessus pour

MERGE target 
USING source ON [my condtion] 
WHEN NOT MATCHED BY TARGET 
THEN INSERT VALUES (source.col1, source.col2, source.col3) 

Mais le problème pour moi est de dire que si j'ai plus de 20 colonnes dans ma table source, je dois tous les lister, j'ai besoin d'un moyen de le spécifier pour insérer la source. *. Y a-t-il un moyen? Je suis nouveau à SQL. Apprécier ton aide.

Merci à l'avance :)

+0

@campbell - thx pour l'info .. hmm .. – tamizhan

Répondre

1

Moi aussi; Je déteste taper des noms de colonnes.

Je construis normalement l'instruction de fusion dans SQL dynamique.
j'ai une fonction qui prend un nom de table comme paramètre, et retourne une chaîne contenant tous les noms de colonnes correctement formaté avec le préfixe Nom de la table, crochets [] et virgule, comme dans S.Col1, S.Col2, S.Col3

Je pourrais aussi vous dire que je construis une table temporaire avec les colonnes nécessaires et passer la table temporaire à ma fonction, parce que quelques fois vous ne voulez pas une liste de toutes les colonnes. Mais ce serait probablement un wooble confus, obscurcissant les morceaux importants;

  1. utilisation sql dynamique
  2. Utilisez une fonction pour créer une liste csv des colonnes.
+0

faire this'd choses plus facile .. vais essayer cela. – tamizhan

1

Tout ce que j'ai lu au sujet de la déclaration MERGE dit que vous devez spécifier les colonnes de votre déclaration INSERT. Si vous cherchez un moyen rapide d'obtenir le statut INSERT, vous pouvez cliquer droit sur la table dans SSMS et sélectionner Table de script As-> INSERT To-> Clipboard. Vous pouvez ensuite coller cela dans votre requête et modifier seulement la partie VALUES.

Merge statement

1

Il n'y a simplement aucun avantage d'utiliser MERGE dans cette situation. Pourquoi trop compliqué? S'en tenir au principe KISS, pour chrissake.

Quoi qu'il en soit, voici le script:

declare 
    @targetTableName varchar(100) = 'target' 
    ,@targetSchemaName varchar(20) = 'dbo' 
    ,@sourceTableName varchar(100) = 'source' 
    ,@sourceSchemaName varchar(20) = 'dbo2' 
    ,@matchCondition varchar(50) = 't.id = s.id' 
    ,@columns varchar(max) 

set @columns = (select ','+quotename(c.name) 
from sys.tables t 
join sys.columns as c on t.object_id = c.object_id 
join sys.schemas s on s.schema_id = t.schema_id 
where t.name = @targetTableName and s.name = isnull(@targetSchemaName, s.name) 
for xml path('')) 

--a column name starts with a comma 

declare @sql varchar(max) = ' 
merge @target t 
using @source s on @matchCondition 
when not matched then 
insert (@columns) 
values @sourceColumns' 

set @sql = 
replace(replace(replace(replace(replace(@sql 
, '@matchCondition', @matchCondition) 
--replace @columns with column list with the first comma removed 
, '@columns', stuff(@columns, 1, 1, '')) 
--replace @sourceColumns with column list with the 's.' prefix and comma removed 
, '@sourceColumns', stuff(replace(@columns, ',', ',s.'),1,1,'')) 
, '@target', quotename(@targetSchemaName)+'.'+quotename(@targetTableName)) 
, '@source', quotename(@sourceSchemaName)+'.'+quotename(@sourceTableName)) 

print @sql 
--exec(@sql) 

Et nous allons obtenir quelque chose comme ceci:

merge [dbo].[target] t 
using [dbo2].[source] s on t.id = s.id 
when not matched then 
insert ([column1], [column2], [column3], [column4]) 
values s.[column1], s.[column2], s.[column3], s.[column4] 
+0

Denis- Non, je l'ai trouvé beaucoup plus optimisé. J'avais un 5 lakh + lignes dans ma table source qui a causé la première requête pour environ 45-50 minutes. La modification de la commande MERGE l'a complétée en quelques secondes :-D :-D Donc j'ai définitivement besoin d'un changement. – tamizhan

+0

Cela n'a tout simplement aucun sens. MERGE réduit à INSERT simple ne peut pas fonctionner mieux ou moins bien que ce dernier. Je ne peux pas me contenter de ce que vous venez de dire. : D –

+0

En ce qui concerne la requête de longue durée, avez-vous essayé de spécifier "with (nolock)" sur la table source? Et croyez-moi, MERGE ne peut tout simplement pas mieux fonctionner. –

Questions connexes