2008-12-09 4 views
6

Ma table comporte un grand nombre de colonnes. J'ai une commande pour copier certaines données - je pense à cloner un produit - mais comme les colonnes peuvent changer à l'avenir, je voudrais seulement sélectionner tout de la table et changer seulement la valeur d'une colonne sans avoir à se référer à le reste.Comment copier un enregistrement, en ne modifiant que l'identifiant?

Par exemple, au lieu de:

INSERT INTO MYTABLE (
SELECT NEW_ID, COLUMN_1, COLUMN_2, COLUMN_3, etc 
FROM MYTABLE) 

Je voudrais quelque chose qui ressemble à

INSERT INTO MYTABLE (
SELECT * {update this, set ID = NEW_ID} 
FROM MYTABLE) 

est-il un moyen simple de le faire?

Il s'agit d'une base de données DB2 sur un iSeries, mais les réponses pour toutes les plates-formes sont les bienvenues.

Répondre

10

Vous pouvez le faire:

create table mytable_copy as select * from mytable; 
update mytable_copy set id=new_id; 
insert into mytable select * from mytable_copy; 
drop table mytable_copy; 
+2

Vous pouvez faire la première ligne avec une commande SELECT INTO . –

1

Votre exemple devrait presque fonctionner. Ajoutez simplement les noms de colonnes de la nouvelle table.


INSERT INTO MYTABLE 
(id, col1, col2) 
SELECT new_id,col1, col2 
FROM TABLE2 
WHERE ...; 
+1

que seules les données des copies pour les colonnes spécifiées - mon objectif est d'éviter la liste chaque colonne. Je vais clarifier la question - merci. –

+1

qu'en est-il de créer une fonction ou un proc stocké ou quoi que ce soit qui construit la requête dynamiquement pour vous? – Salamander2007

+0

Toujours signifie que vous devez spécifier les champs si ... –

3

Je ne pense pas que ce soit tout à fait faisable dans SQL sans se donner la peine de créer une table temporaire. Le faire en mémoire devrait être beaucoup plus rapide. Méfiez-vous si vous allez sur la route table temporaire que vous devez choisir un nom unique pour votre table pour chaque invocation de fonction pour éviter la condition de course où votre code s'exécute deux fois en même temps et mange deux lignes de données dans une table temporaire.

Je ne sais pas quel type de langage vous utilisez mais il devrait être possible d'obtenir une liste de champs dans votre programme. Je le ferais comme ceci:

array_of_field_names = conn->get_field__list; 
array_of_row_values = conn->execute ("SELECT... "); 
array_of_row_values ["ID"] = new_id_value 
insert_query_string = "construct insert query string from list of field names and values"; 
conn->execute (insert_query_string); 

Ensuite, vous pouvez encapsuler qu'en fonction et simplement l'appeler en spécifiant la table, vieux et id nouvel identifiant et il travaillerait c'est magique.

Dans le code Perl l'extrait suivant ferait:

$table_name = "MYTABLE"; 
$field_name = "ID"; 
$existing_field_value = "100"; 
$new_field_value = "101"; 

my $q = $dbh->prepare ("SELECT * FROM $table_name WHERE $field_name=?"); 
$q->execute ($existing_field_value); 
my $rowdata = $q->fetchrow_hashref; # includes field names 
$rowdata->{$field_name} = $new_field_value; 

my $insq = $dbh->prepare ("INSERT INTO $table_name (" . join (", ", keys %$rowdata) . 
    ") VALUES (" . join (", ", map { "?" } keys %$rowdata) . ");"; 
$insq->execute (values %$rowdata); 

Hope this helps.

2

Ok, essayez ceci:

declare @othercols nvarchar(max); 
declare @qry nvarchar(max); 

select @othercols = (
select ', ' + quotename(name) 
from sys.columns 
where object_id = object_id('tableA') 
and name <> 'Field3' 
and is_identity = 0 
for xml path('')); 

select @qry = 'insert mynewtable (changingcol' + @othercols + ') select newval' + @othercols; 

exec sp_executesql @qry; 

Avant d'exécuter la ligne « sp_executesql », s'il vous plaît faire «sélectionnez @qry » pour voir ce que la commande est que vous allez courir.

Et bien sûr, vous pouvez coller ceci dans une procédure stockée et transmettre une variable au lieu du bit 'Field3'.

Rob

+0

Je devrais mentionner - c'est une version de SQL Server 2005+ ... –

+0

Oui, je peux faire quelque chose de semblable avec le catalogue de système de DB2. Je vais voir ce que la performance est par rapport à la technique de copie-copie si j'ai le temps. Merci. –

+0

Et bien sûr, si vous voulez seulement certaines lignes, ajoutez simplement une clause WHERE à @qry. –

-1

je ne l'ai jamais travaillé avec db2 mais MSSQL vous pouvez le résoudre avec la procédure suivante. cette solution ne fonctionne que si vous ne vous souciez pas de ce que les nouveaux éléments obtiennent. 1.12 créer une nouvelle table avec le même schéma mais où la colonne id s'incrémente automatiquement. (mssql "spécification d'identité = 1, incrément d'identité = 1)

2.) Qu'un simple

insert into newTable(col1, col2, col3) 
select (col1, col2, col3) from oldatable 

devrait être suffisant, assurez-vous de ne pas inclure votre identifiant Colum dans la déclaration ci-dessus