Una stored procedure per la duplicazione delle righe di una tabella generica 25 Aprile 2008
Posted by gianfrasoft in Transact SQL.Tags: COLUMNS, duplicazione, generica, INFORMATION_SCHEMA, righe, tabella, Una stored procedure per la duplicazione delle righe di
trackback
Duplicare la riga di una tabella è una operazione sempre possibile ma spesso non immediata: la tabella in questione può essere caratterizzata dalla presenza di una chiave univoca che coinvolga uno o più campi, da campi NOT NULL che vanno valorizzati talora con i propri valori di default, ecc…
Lo script INSERT che effettua l’inserimento di una riga duplicata deve, nella maggior parte dei casi, specificare la lista dei campi da caricare nel nuovo record e questo perché lo script non deve definire valori duplicati per i campi chiave, se richiesto non deve sovrascrivere i valori di default, non deve definire valori per i campi auto-incrementali e quant’altro.
Consideriamo il caso, piuttosto diffuso, di tabelle caratterizzate da una chiave primaria composta da un campo auto-incrementale, e realizziamo una procedura che:
- sia in grado di semplificare l’operazione di duplicazione della riga di una tabella, agendo indipendentemente dalla struttura della stessa;
- restituisca l’indice univoco del campo chiave del nuovo record;
- non valorizzi i campi che hanno valori di default;
- agisca su una qualsiasi tabella dove sia presente una chiave primaria composta da un campo auto-incrementale.
Il cuore della procedura è nella generazione al volo di uno script di insert completo della lista esplicita di tutti i campi della tabella su cui andiamo a duplicare il record. La lista dei campi viene recuperata mediante la view di sistema INFORMATION_SCHEMA mentre una chiamata alla stored procedure di sistema sp_executesql permetterà di eseguire lo script INSERT appena creato.
La procedura in questione esporrà, pertanto, tra i parametri:
- il nome della tabella della quale s’intende duplicare una riga,
- il nome del campo chiave,
- l’id univoco della riga che si vuole duplicare
e restituirà l’id del record duplicato generato. Ecco il codice commentato:
IF EXISTS (SELECT SPECIFIC_NAME FROM INFORMATION_SCHEMA.ROUTINES WHERE SPECIFIC_NAME = ‘ClonaRecord’) DROP PROCEDURE dbo.ClonaRecord GO CREATE PROCEDURE dbo.ClonaRecord( @Tabella varchar(90), @NomeCampoID varchar(90), @IDSorgente varchar(16), @IDDestinazione varchar(16) OUTPUT ) AS BEGIN DECLARE @ErrMsg nvarchar(4000), @ErrSeverity int IF @IDSorgente IS NULL BEGIN SET @IDDestinazione = ‘ERROR’ — Verifica che il campo @NomeCampoID non sia nullo. Se lo è, solleva un’eccezione SELECT @ErrMsg = ‘Errore nei parametri - ‘ + @NomeCampoID + ‘ nullo.’, @ErrSeverity = 1 RAISERROR(@ErrMsg, @ErrSeverity, 1) RETURN END DECLARE @i int DECLARE @Script nvarchar(max) — PROCESSAMENTO – BEGIN TRY — La procedura lavora con le transazioni BEGIN TRANSACTION DECLARE @IDValue varchar(100) DECLARE @Fields nvarchar(max) DECLARE @Ordinal integer SET @Script = ” — La procedura inoltre accede alla view di sistema INFORMATION_SCHEMA — per recuperare la lista dei campi indispensabili per la generazione — dello script di INSERT SELECT @Ordinal = MIN(ORDINAL_POSITION) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @Tabella WHILE @Ordinal IS NOT NULL BEGIN SELECT @IDValue = COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @Tabella AND ORDINAL_POSITION = @Ordinal — Un ciclo sul recordset individuato nella view INFORMATION_SCHEMA — permette di popolare la stringa @Fields destinate a contenere la — lista dei campi IF @IDValue <> @NomeCampoID BEGIN IF @Fields IS NULL SET @Fields = @IDValue ELSE SET @Fields = @Fields + ‘, ‘ + @IDValue END SELECT @Ordinal = MIN(ORDINAL_POSITION) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @Tabella AND ORDINAL_POSITION > @Ordinal AND COLUMN_DEFAULT IS NULL — * NEW * – END — Ecco finalmente lo script INSERT che viene generato al volo nell’ambito — della stringa @Script di dimensioni nvarchar(max) SET @Script = ‘INSERT INTO ‘ + @Tabella + ‘ (’ + @Fields + ‘)’ + ‘ SELECT ‘ + @Fields + ‘ FROM ‘ + @Tabella + ‘ WHERE ‘ + @NomeCampoID + ‘ = ”’ + @IDSorgente + ”” — Lo script viene eseguito EXECUTE sp_executesql @Script — Nella variabile @IDDestinazione viene conservato l’IDENTITY del nuovo — record SET @IDDestinazione = @@IDENTITY COMMIT TRANSACTION END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK SET @IDDestinazione = ‘ERROR’ — Se @IDDestinazione non è stato popolato, solleva un’eccezione SELECT @ErrMsg = ERROR_MESSAGE(), @ErrSeverity = ERROR_SEVERITY() RAISERROR(@ErrMsg, @ErrSeverity, 1) END CATCH END GO
Un esempio di chiamata alla procedura appena descritta è riportata di seguito:
DECLARE @IDDestinazione varchar(16); EXECUTE dbo.DuplicateRecord 'test', 'id', '6', @IDDestinazione OUTPUT PRINT 'Nuovo id: ' + @IDDestinazione
dove alla chiamata segue la stampa nello standard output di SQL Server dell’id univoco del record appena generato.
Commenti»
No comments yet — be the first.