Creazione trigger su SQL SERVER 2008 EXPRESS

mercoledì 25 marzo 2009 - 09.51

gderossi Profilo | Newbie

Ciao a tutti

Sto cercando di creare il seguente trigger su SQL SERVER 2008 EXPRESS:

USE [C:\DB_GEDECAR\GEDECAR.MDF]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[AGG_DAS_ACQD] ON [dbo].[DAS_ACQD] AFTER INSERT AS
BEGIN
SET NOCOUNT ON;
DECLARE @id int, @datac DATETIME, @fornitore INT, @mese VARCHAR, @anno VARCHAR
SELECT @id = m.dam_id, @datac = m.dam_data, @fornitore = m.dam_for_id, @mese = m.dam_mese, @anno = m.dam_anno
FROM [dbo].[DAS_ACQM] AS m
WHERE m.DAM_ID = [dbo].[DAS_ACQD].[DAD_DAM_ID];
UPDATE [dbo].[DAS_ACQD]
SET [DAD_DATA] = @datac, [DAD_FOR_ID] = @fornitore, [DAD_MESE] = @mese, [DAD_ANNO] = @anno
WHERE [dbo].[DAS_ACQD].[DAD_DAM_ID] = @id;
END
GO

però mi da il seguente errore:

Messaggio 4104, livello 16, stato 1, procedura AGG_DAS_ACQD, riga 8
Impossibile associare l'identificatore in più parti "dbo.DAS_ACQD.DAD_DAM_ID".

Dove sto sbagliando ?

Grazie e Ciao
Giuseppe

lbenaglia Profilo | Guru

>Dove sto sbagliando ?

Ciao Giuseppe,

Cosa dovrebbe fare quel trigger?
Puoi postare un esempio completo con la struttura delle tabelle (CREATE TABLE), alcune righe di prova (INSERT INTO) ed il risultato finale che vuoi ottenere.

>Grazie e Ciao
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

gderossi Profilo | Newbie

L'errore non me lo da a runtime ma a designtime, quindi non ho righe di prova con INSERT INTO.

Quello che vorrei fare quando inserisco e salvo un record della tabella DAS_ACQD
è di replicare le colonne DAM_DATA, DAM_FOR_ID, DAM_MESE, DAM_ANNO della tabella DAS_ACQM
nelle corrispondenti colonne DAD_DATA, DAD_FOR_ID, DAD_MESE, DAD_ANNO della tabella DAS_ACQD.

Spero di essere stato chiaro.

CREATE TABLE DAS_ACQM(
DAM_ID int IDENTITY(1,1) NOT NULL,
DAM_NUM varchar (12) NOT NULL,
DAM_DOC_AMM varchar(12) NULL,
DAM_DATA datetime NOT NULL,
DAM_FOR_ID int NOT NULL,
DAM_MOTRICE varchar(12) NOT NULL,
DAM_RIMORCHIO varchar(12) NULL,
DAM_AUTISTA varchar(30) NULL,
DAM_MESE varchar(2) NOT NULL,
DAM_ANNO varchar(4) NOT NULL,
CONSTRAINT PK_DAS_ACQM PRIMARY KEY CLUSTERED (DAM_ID ASC)

ALTER TABLE DAS_ACQM WITH CHECK ADD CONSTRAINT FK_DAS_ACQM_FORNITORI
FOREIGN KEY(DAM_FOR_ID) REFERENCES FORNITORI (FOR_ID)

ALTER TABLE DAS_ACQM CHECK CONSTRAINT FK_DAS_ACQM_FORNITORI


CREATE TABLE DAS_ACQD(
DAD_ID int IDENTITY(1,1) NOT NULL,
DAD_DAM_ID int NOT NULL,
DAD_NUM varchar(12) NULL,
DAD_DOC_AMM varchar(12) NULL,
DAD_FOR_ID int NULL,
DAD_DATA datetime NULL,
DAD_ART_ID varchar(10) NOT NULL,
DAD_LT int NOT NULL,
DAD_LT15 int NULL,
DAD_KG int NOT NULL,
DAD_DENS numeric(5, 4) NULL,
DAD_DENS15 numeric(5, 4) NULL,
DAD_MESE varchar(2) NULL,
DAD_ANNO varchar(4) NULL,
CONSTRAINT PK_DAS_ACQD PRIMARY KEY CLUSTERED (DAD_ID ASC)

ALTER TABLE DAS_ACQD WITH CHECK ADD CONSTRAINT FK_DAS_ACQD_DAS_ACQM
FOREIGN KEY(DAD_DAM_ID) REFERENCES DAS_ACQM (DAM_ID)

ALTER TABLE DAS_ACQD CHECK CONSTRAINT FK_DAS_ACQD_DAS_ACQM


ALTER TABLE DAS_ACQD WITH CHECK ADD CONSTRAINT FK_DAS_ACQD_ARTICOLI
FOREIGN KEY(DAD_ART_ID) REFERENCES ARTICOLI (ART_ID)

ALTER TABLE DAS_ACQD CHECK CONSTRAINT FK_DAS_ACQD_ARTICOLI

Mi potresti consigliare un buon manuale su SQL SERVER 2008 ?

Ancora grazie e ciao.

Giuseppe

lbenaglia Profilo | Guru

>Quello che vorrei fare quando inserisco e salvo un record della
>tabella DAS_ACQD
>è di replicare le colonne DAM_DATA, DAM_FOR_ID, DAM_MESE, DAM_ANNO
>della tabella DAS_ACQM
>nelle corrispondenti colonne DAD_DATA, DAD_FOR_ID, DAD_MESE,
>DAD_ANNO della tabella DAS_ACQD.

Prova a vedere se questo trigger soddisfa le tue esigenze:

CREATE TRIGGER dbo.AGG_DAS_ACQD ON dbo.DAS_ACQD AFTER INSERT AS UPDATE M SET DAD_DATA = M.DAM_DATA , DAD_FOR_ID = M.DAM_FOR_ID , DAD_MESE = M.DAM_MESE , DAD_ANNO = M.DAM_ANNO FROM dbo.DAS_ACQM AS M JOIN INSERTED AS D ON M.DAM_ID = D.DAD_DAM_ID;

La tabella virtuale INSERTED contiene tutte le righe inserite nella tabella dbo.DAS_ACQD.
A questo punto è sufficiente eseguire una JOIN con la tabella di destinazione dbo.DAS_ACQM aggiornando le colonne che ti interessano.

>Mi potresti consigliare un buon manuale su SQL SERVER 2008 ?
Ne esistono parecchi.
Che argomento vuoi approfondire?

>Ancora grazie e ciao.
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

gderossi Profilo | Newbie

Ciao Lorenzo, grazie per l'aiuto.

Ho modificato il codice che hai postato nella seguente maniera, perchè la tabella da aggiornare è DAS_ACQD, quindi D e non M,

USE [C:\DB_GEDECAR\GEDECAR.MDF]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER dbo.AGG_DAS_ACQD
ON dbo.DAS_ACQD
AFTER INSERT
AS
UPDATE D
SET DAD_DATA = M.DAM_DATA
, DAD_FOR_ID = M.DAM_FOR_ID
, DAD_MESE = M.DAM_MESE
, DAD_ANNO = M.DAM_ANNO

FROM dbo.DAS_ACQM AS M
JOIN INSERTED AS D
ON M.DAM_ID = D.DAD_DAM_ID;

ma mi da il seguente errore:

Messaggio 286, livello 16, stato 1, procedura AGG_DAS_ACQD, riga 6
Impossibile aggiornare le tabelle logiche INSERTED e DELETED.

Dove sto sbagliando ????????????

Per quanto riguarda il libro mi interessa soprattutto il linguaggio Transact-SQL.
Ho una buona esperienza su DB Oracle, ottime conoscenze su SQL e PL/SQL (in Oracle un trigger del genere lo avrei fatto ad occhi chiusi).
Ancora grazie

lbenaglia Profilo | Guru

>UPDATE D
...
>FROM dbo.DAS_ACQM AS M
>JOIN INSERTED AS D
>ON M.DAM_ID = D.DAD_DAM_ID;
>
>ma mi da il seguente errore:
>
>Messaggio 286, livello 16, stato 1, procedura AGG_DAS_ACQD, riga
>6
>Impossibile aggiornare le tabelle logiche INSERTED e DELETED.
>
>Dove sto sbagliando ????????????

INSERTED e DELETED sono tabelle virtuali che contengono rispettivamente le nuove righe inserite e quelle eliminate dalla transazione corrente, quindi non possono essere modificate (non avrebbe alcun senso).

Modifica il trigger nel seguente modo:

CREATE TRIGGER dbo.AGG_DAS_ACQD ON dbo.DAS_ACQD AFTER INSERT AS UPDATE dbo.DAS_ACQD SET DAD_DATA = M.DAM_DATA , DAD_FOR_ID = M.DAM_FOR_ID , DAD_MESE = M.DAM_MESE , DAD_ANNO = M.DAM_ANNO FROM dbo.DAS_ACQM AS M JOIN INSERTED AS D ON M.DAM_ID = D.DAD_DAM_ID;

>Ancora grazie
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

gderossi Profilo | Newbie

Leggendo MSDN avevo già capito che la soluzione era questa ( in pratica DELETED corrisponde a :OLD.colonna e INSERTED A :NEW.colonna), e in questo modo funziona, però mi aggiorna tutte le righe non solamente quelle legate al master.

Ho modificato il trigger in questa maniera ma non va lo stesso:

USE [C:\DB_GEDECAR\GEDECAR.MDF]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[AGG_DAS_ACQD]
ON [dbo].[DAS_ACQD]
AFTER INSERT
AS
UPDATE dbo.DAS_ACQD
SET DAD_DATA = M.DAM_DATA
, DAD_FOR_ID = M.DAM_FOR_ID
, DAD_MESE = M.DAM_MESE
, DAD_ANNO = M.DAM_ANNO

FROM dbo.DAS_ACQM AS M
JOIN INSERTED AS D
ON M.DAM_ID = D.DAD_DAM_ID
where D.DAD_DAM_ID = M.DAM_ID;

E' la where condition che non va sicuramente.

Per il libro che mi dici ?

Ciao

lbenaglia Profilo | Guru

>Leggendo MSDN avevo già capito che la soluzione era questa (
>in pratica DELETED corrisponde a :OLD.colonna e INSERTED A :NEW.colonna),
>e in questo modo funziona, però mi aggiorna tutte le righe non
>solamente quelle legate al master.
Vero

>E' la where condition che non va sicuramente.
Prova così:

CREATE TRIGGER dbo.AGG_DAS_ACQD ON dbo.DAS_ACQD AFTER INSERT AS UPDATE D SET DAD_DATA = M.DAM_DATA , DAD_FOR_ID = M.DAM_FOR_ID , DAD_MESE = M.DAM_MESE , DAD_ANNO = M.DAM_ANNO FROM dbo.DAS_ACQM AS M JOIN INSERTED AS I ON M.DAM_ID = I.DAD_DAM_ID JOIN dbo.DAS_ACQD AD D ON D.DAD_ID = I.DAD_ID;

>Per il libro che mi dici ?
Sei tu che non mi hai ancora detto quale argomento vuoi approfondire

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

gderossi Profilo | Newbie


Funziona alla grande.
Grazie veramente.

Per quanto riguarda il libro mi interessa soprattutto il linguaggio Transact-SQL.
Ho una buona esperienza su DB Oracle, ottime conoscenze su SQL e PL/SQL (in Oracle un trigger del genere lo avrei fatto ad occhi chiusi).

Giuseppe

lbenaglia Profilo | Guru

>Per quanto riguarda il libro mi interessa soprattutto il linguaggio
>Transact-SQL.
OK, giusto ieri è uscito il nuovo libro di Itzik:
Inside Microsoft® SQL Server® 2008: T-SQL Querying
http://www.microsoft.com/learning/en/us/Books/12804.aspx

Tra non molto pubblicherà Inside Microsoft® SQL Server® 2008: T-SQL Programming che completerà il discorso programmazione (T-SQL, XML e .Net) per la versione 2008 di SQL Server.

>Ho una buona esperienza su DB Oracle, ottime conoscenze su SQL
>e PL/SQL (in Oracle un trigger del genere lo avrei fatto ad occhi
>chiusi).
Eh, l'hai già detto

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

ziobestia Profilo | Newbie


>INSERTED e DELETED sono tabelle virtuali che contengono rispettivamente
>le nuove righe inserite e quelle eliminate dalla transazione
>corrente, quindi non possono essere modificate (non avrebbe alcun
>senso).

Ma se io volessi invece modificare alcuni campi di quello che sto inserendo ???
Esempio se durante la insert il programma scrive un campo data dal quale io mi volessi estrarre l'anno e inserirlo in una colonna della stessa tabella ?

Saluti Marco

lbenaglia Profilo | Guru

>Ma se io volessi invece modificare alcuni campi di quello che
>sto inserendo ???
>Esempio se durante la insert il programma scrive un campo data
>dal quale io mi volessi estrarre l'anno e inserirlo in una colonna
>della stessa tabella ?

Ciao Marco,

Modificherei la struttura della tabella prevedendo una colonna calcolata che restituisca l'informazione richiesta lasciando perdere i triggers.
Per maggiori info dai un'occhiata al seguente paragrafo dei Books Online:
http://msdn.microsoft.com/en-us/library/ms191250.aspx

>Saluti Marco
Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/

ziobestia Profilo | Newbie

hai perfettamente ragione, se potessi cambiarmi il tracciato record, ma non potendo intervenire in tal maniera e non potendo modificare il programma sarebbe l'unica soluzione, comunque provando alla fine ho fatto così :

ALTER trigger [dbo].[campi_default] on [dbo].[tabella]
for insert
as
begin
update tabella set campo = 'Italiano'
where ID = (select ID from inserted) and campo is null
end

lbenaglia Profilo | Guru

>alla fine ho fatto così :
>
>ALTER trigger [dbo].[campi_default] on [dbo].[tabella]
>for insert
>as
>begin
>update tabella set campo = 'Italiano'
>where ID = (select ID from inserted) and campo is null
>end

Occhio che questo codice non funzionerà nel caso in cui vai ad aggiornare più di una riga.
Modifica il trigger in questo modo:

ALTER TRIGGER [dbo].[campi_default] ON [dbo].[tabella] FOR INSERT AS UPDATE T SET campo = 'Italiano' FROM dbo.tabella AS T JOIN INSERTED I ON T.ID = I.ID WHERE T.campo IS NULL;

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5