2008-09-29 8 views
1

Existe-t-il un moyen propre de cloner un enregistrement dans SQL qui a un index (incrémentation automatique). Je veux cloner tous les champs sauf l'index. Je dois actuellement énumérer tous les champs, et les utiliser dans un insert select, et je préfère ne pas lister explicitement tous les champs, car ils peuvent changer avec le temps.Enregistrement clone SQL avec un index unique

Répondre

1

Non, sauf si vous voulez entrer dans le SQL dynamique. Puisque vous avez écrit "propre", je suppose que non.

Editer: Puisqu'il a demandé un exemple SQL dynamique, je vais essayer de le faire. Je ne suis pas connecté à une base de données pour le moment, donc cela me vient à l'esprit et nécessitera certainement une révision. Mais nous espérons qu'il capte l'esprit des choses:

-- Get list of columns in table 
SELECT INTO #t 
EXEC sp_columns @table_name = N'TargetTable' 

-- Create a comma-delimited string excluding the identity column 
DECLARE @cols varchar(MAX) 
SELECT @cols = COALESCE(@cols+',' ,'') + COLUMN_NAME FROM #t WHERE COLUMN_NAME <> 'id' 

-- Construct dynamic SQL statement 
DECLARE @sql varchar(MAX) 
SET @sql = 'INSERT INTO TargetTable (' + @cols + ') ' + 
    'SELECT ' + @cols + ' FROM TargetTable WHERE SomeCondition' 

PRINT @sql -- for debugging 
EXEC(@sql) 
+0

avez-vous un exemple utilisant dynamic sql? – Milhous

+0

Est-ce spécifique à MySQL? La syntaxe SELECT INTO avec les données provenant de la commande EXEC stmt ne fonctionne pas sur SQL Server AFAIK. – Codewerks

+0

Non, il était destiné à être SQL Server. Je ne me souviens pas si cela a fonctionné. Sinon, vous pouvez créer la table temporaire explicitement, puis utiliser INSERT INTO #t EXEC sp_columns ... –

0

Vous pouvez créer cependant un déclencheur d'insertion pour ce faire, vous perdez la possibilité de faire un insert avec un ID explicite. Au lieu de cela, il utiliserait toujours la valeur de la séquence.

1

Il n'y a pas de manière facile et propre que je puisse penser à la tête, mais à partir de quelques éléments de votre question, je serais préoccupé par votre architecture sous-jacente. Peut-être avez-vous une raison absolument légitime de vouloir faire cela, mais habituellement vous voulez essayer d'éviter les doublons dans une base de données, pas les rendre plus faciles à provoquer. En outre, nommer explicitement des colonnes est généralement une bonne idée. Si vous créez un lien vers un code externe, vous vous assurez de ne pas rompre ce lien lorsque vous ajoutez une nouvelle colonne. Si ce n'est pas le cas (et il semble que vous ne soyez probablement pas dans ce scénario), je préfère quand même que les colonnes soient listées car cela m'oblige à revoir les effets du changement/de la nouvelle colonne - même si c'est juste pour regarder le code et décidez que l'ajout de la nouvelle colonne n'est pas un problème.

+0

Nos clients créeront un clone d'un article. Tous les attributs de l'élément sont les mêmes, sauf qu'il s'agit d'une nouvelle entrée dans la table (nouvel index) et qu'elle aura une référence de clé étrangère différente. – Milhous

+1

Il semble que ce que vous cherchez devrait vraiment être fait dans l'interface utilisateur. Dans le cadre de votre écran d'édition normal pour les éléments, laissez-les pré-remplir les champs avec des informations provenant d'un élément existant. À ce moment, c'est juste une sauvegarde normale. Si vous ajoutez de nouvelles colonnes, vous devrez quand même modifier cet écran. –

0

Vous pouvez créer un déclencheur pour le faire pour vous. Pour vous assurer que le trigger fonctionne uniquement pour le clonage, vous pouvez créer un nom d'utilisateur distinct CLONE et vous connecter avec. Ou, mieux encore, si votre SGBD le supporte, créez un rôle nommé CLONE et n'importe quel utilisateur peut se connecter à l'aide de ce rôle et effectuer le clonage. Le code de déclenchement serait quelque chose comme:

if (CURRENT_ROLE = 'CLONE') then 
    new.ID = assign new id from generator/sequence 

Bien sûr, vous accorderait ce rôle uniquement aux utilisateurs qui sont autorisés à cloner les enregistrements.

0
DROP TABLE #tmp_MyTable 

SELECT * INTO #tmp_MyTable 
FROM MyTable 
WHERE MyIndentID = 165 

ALTER TABLE #tmp_MyTable 
DROP Column MyIndentID 

INSERT INTO MyTable 
SELECT * 
FROM #tmp_MyTable 
1

Cela concerne également un projet clé unique ainsi que la clé primaire.

CREATE TEMPORARY TABLE projecttemp SELECT * FROM project WHERE projectid='6'; 
ALTER TABLE projecttemp DROP COLUMN projectid; 
UPDATE projecttemp SET projectnum = CONCAT(projectnum, ' CLONED'); 
INSERT INTO project SELECT NULL,projecttemp.* FROM projecttemp; 
Questions connexes