Dupliquer une ligne avec une col. en autoincrement

j’ai une petite question SQL (server200X), dont je ne trouve pas la solution sur le net

voila un exemple du pb :
j’ai une table simple:


CREATE TABLE [dbo].[test](
	[id] [int] IDENTITY(1,1) NOT NULL,
	[toto] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
	[titi] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
 CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED 
(
	[id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

et je voudrait faire une requette qui sert a dupliquer une ligne (pas sorcier a la base :smiley: )

insert into test select * from test where id= 2

sauf que, vous l’avez compris, je ne veux pas m’amuser a saisir les colonnes a la place du *
Dans mon cas concret j’ai une bonne quantité de colonnes et comme la requette est dans une
proc. stock je voudrait éviter d’y retourner si je rajoute une colonne a la table concernée.

En bidouillant (proprement) en utilisant des variables systèmes ? (syscolunms, systypes)

A mon avis, si ça existe, c’est dans ton cas du spécifique server200X. Tu devrais donc envisager une solution en regardant la documentation de server200X sur l’insert into … select

de base c’est impossible de faire ce que j’ai exposé, et ca doit etre valable pour tous les systèmes de DB
en gros, faudrait créer une fonction sql qui prend en paramètre :

  • le nom de la table (ex : ‘test’)
  • la condition de la ligne a insérer (ex : ‘where id= 2’)
    et cette dite fonction doit être capable de créer la requette suivante :
insert into test (toto,titi) select toto,titi from test where id= 2

avec les variables syscolunms j’arrive à récupérer les noms des colonnes
mais je n’arrive pas à identifier quand une colonne est un Primary Key

Pour sql 2005 et + tu peux utiliser cet example, pour sql 2000 il faut changer le nom des tables systeme.

Declare @i int, @iMax int, @ColumnList varchar(max)
Declare @tmpTable table (ID int identity(1,1) primary key, ColumnName varchar(255) not null)

Insert @tmpTable (ColumnName)
Select a.name
From sys.columns a
        Join sys.tables b on b.object_id = a.object_id
Where b.name = 'test'
        And a.is_identity = 0
Order by a.column_id

Select @i = 1, @iMax = max(ID), @ColumnList = '' From @tmpTable

While @i<=@iMax
Begin
        Select @ColumnList = @ColumnList + ColumnName From @tmpTable where ID = @i
        If @i<@iMax Set @ColumnList = @ColumnList + ', '
        Set @i = @i + 1
End

Exec('Insert test (' + @ColumnList + ') Select ' + @ColumnList + ' From test where id = 2') 

Pour savoir si une colonne ne fais pas partie de la primary key tu peux faire ca:

Select a.name
From sys.columns a
	Join sys.tables b on b.object_id = a.object_id
	Left Join sys.indexes c on c.object_id = b.object_id
	Left Join sys.index_columns d on d.object_id = b.object_id and d.index_id = c.index_id
Where b.name = 'MyTest'
	And d.column_id != a.column_id
	And c.is_primary_key = 1
	--And a.is_identity = 0
Order by a.column_id

Edité le 18/12/2009 à 18:42