Problema viste

mercoledì 19 aprile 2006 - 15.02

scandian Profilo | Newbie

ho creato una vista su una join tra due tabelle, il problema è che quando faccio una insert sulla vista, non parte il trigger di insert, ma la vista si arrangia ad inserirmi nella prima tabella i valori, anche se non è presente alcun trigger....
come faccio a disattivare tale funzione??

lbenaglia Profilo | Guru

>ho creato una vista su una join tra due tabelle, il problema
>è che quando faccio una insert sulla vista, non parte il trigger
>di insert, ma la vista si arrangia ad inserirmi nella prima tabella
>i valori, anche se non è presente alcun trigger....

Ciao scandian,

non è necessaria la presenza di un trigger di INSERT per popolare *UNA SOLA* delle tabelle base utilizzate in una vista.
Nei links che ti ho suggerito ieri (http://www.dotnethell.it/forum/messages.aspx?ThreadID=7388) è spiegato chiaramente quando è necessario ricorrere ai triggers INSTEAD OF per aggiornare, inserire o eliminare rige tramite viste.

>come faccio a disattivare tale funzione??
Devi lavorare a livello di permission.
Leggi molto attentamente questo articolo di Luca Bianchi:
http://www.microsoft.com/italy/technet/community/mvp/editoriali/permessi.mspx

Ciao!

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

scandian Profilo | Newbie

non so se ha capito.....io non devo creare permessi o altro....devo far partire un trigger !
ho creato il trigger, il problema è che non viene mai eseguito, perchè la vista lavora per conto suo

lbenaglia Profilo | Guru

>non so se ha capito.....io non devo creare permessi o altro....devo
>far partire un trigger !
>ho creato il trigger, il problema è che non viene mai eseguito,
>perchè la vista lavora per conto suo

Posta tutto il codice (tabella, trigger, istruzioni di test e risultato voluto).



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

scandian Profilo | Newbie

tabella:

CREATE TABLE [dbo].[ABC01_FEATURES] (
[COMPANY_ID] [char] (5) COLLATE Latin1_General_CI_AS NOT NULL ,
[SITE_ID] [numeric](5, 0) NOT NULL ,
[FEATURE_ID] [varchar] (20) COLLATE Latin1_General_CI_AS NOT NULL ,
[DESCR_ID] [numeric](20, 0) NOT NULL ,
[STATUS] [char] (1) COLLATE Latin1_General_CI_AS NOT NULL ,
[TIMESTAMP] [numeric](4, 0) NOT NULL ,
[USER_ID] [varchar] (20) COLLATE Latin1_General_CI_AS NOT NULL
) ON [PRIMARY]


tabella2:

CREATE TABLE [dbo].[SYS10_DICTIONARY] (
[COMPANY_ID] [char] (5) COLLATE Latin1_General_CI_AS NOT NULL ,
[SITE_ID] [numeric](5, 0) NOT NULL ,
[LANGUAGE_ID] [varchar] (5) COLLATE Latin1_General_CI_AS NOT NULL ,
[DESCR_ID] [numeric](20, 0) NOT NULL ,
[DESCRIPTION] [varchar] (100) COLLATE Latin1_General_CI_AS NULL ,
[TIMESTAMP] [numeric](4, 0) NOT NULL ,
[USER_ID] [varchar] (20) COLLATE Latin1_General_CI_AS NOT NULL
) ON [PRIMARY]

vista:

CREATE VIEW ABC01_VT_FEATURES AS SELECT A.COMPANY_ID, A.SITE_ID, A.FEATURE_ID, A.DESCR_ID, A.STATUS, A.TIMESTAMP, A.USER_ID, GETDATE() AS CREATE_DATE, A.USER_ID AS USER_ID_CREATE, GETDATE() AS LAST_UPDATE, A.USER_ID AS USER_ID_UPDATE, A.TIMESTAMP ROW_VERSION, 'abc01' AS TABLE_ID, B.DESCRIPTION AS DESCRIPTION, B.LANGUAGE_ID AS LANGUAGE_ID_SYS10 FROM abc01_features A JOIN SYS10_DICTIONARY B
ON A.DESCR_ID= B.DESCR_ID AND A.SITE_ID =B.SITE_ID AND A.COMPANY_ID =B.COMPANY_ID


trigger inserimento:


CREATE TRIGGER abc01_features_BI
ON abc01_VT_features
INSTEAD OF INSERT
AS
DECLARE @DescrID2 NUMERIC,
@COMPANY_ID char(5 ),
@SITE_ID numeric(5 ),
@FEATURE_ID varchar(20),
@DESCR_ID numeric(13),
@STATUS char(1 ),
@TIMESTAMP numeric(5 ),
@USER_ID varchar(20),
@CREATE_DATE DATETIME,
@USER_ID_CREATE VARCHAR(20),
@LAST_UPDATE DATETIME,
@USER_ID_UPDATE VARCHAR(20),
@ROW_VERSION NUMERIC(4),
@TABLE_ID CHAR(10),
@LANGUAGE_ID_SYS10 VARCHAR(5),
@DESCRIPTION VARCHAR(100)
DECLARE INSERITI CURSOR FOR SELECT * FROM INSERTED
IF @@ROWCOUNT =0 RETURN
OPEN INSERITI
FETCH NEXT FROM INSERITI INTO @COMPANY_ID, @SITE_ID, @FEATURE_ID, @DESCR_ID, @STATUS, @TIMESTAMP, @USER_ID, @CREATE_DATE, @USER_ID_CREATE, @LAST_UPDATE, @USER_ID_UPDATE, @ROW_VERSION, @TABLE_ID, @LANGUAGE_ID_SYS10,@DESCRIPTION
WHILE(@@FETCH_STATUS=0)
BEGIN
EXEC NEXT_VALUE_DESCR_ID2 @COMPANY_ID,@SITE_ID,@DescrID2 OUTPUT

INSERT INTO abc01_features( COMPANY_ID, SITE_ID, FEATURE_ID, DESCR_ID, STATUS, TIMESTAMP, USER_ID)
VALUES ( @COMPANY_ID, @SITE_ID, @FEATURE_ID, @DescrID2, isnull(@STATUS,'E'), isnull(@TIMESTAMP,isnull(@ROW_VERSION,0)), @USER_ID)

INSERT INTO SYS10_DICTIONARY (COMPANY_ID,SITE_ID,DESCR_ID,LANGUAGE_ID,DESCRIPTION,USER_ID)
VALUES(@COMPANY_ID,@SITE_ID,@DescrID2,@LANGUAGE_ID_SYS10,@DESCRIPTION,@USER_ID)

FETCH NEXT FROM INSERITI INTO @COMPANY_ID, @SITE_ID, @FEATURE_ID, @DESCR_ID, @STATUS, @TIMESTAMP, @USER_ID, @CREATE_DATE, @USER_ID_CREATE, @LAST_UPDATE, @USER_ID_UPDATE, @ROW_VERSION, @TABLE_ID, @LANGUAGE_ID_SYS10,@DESCRIPTION

END
CLOSE INSERITI
DEALLOCATE INSERITI



funzione richiamata dal trigger:

CREATE PROCEDURE NEXT_VALUE_DESCR_ID2(@V_COMPANY_ID CHAR(5), @V_SITE_ID NUMERIC(5), @O_CURRENT_VALUE NUMERIC(20) OUTPUT)
AS
BEGIN

IF (SELECT COUNT(*) FROM SYS03_SEQUENCES WHERE COMPANY_ID=@V_COMPANY_ID AND SITE_ID=@V_SITE_ID AND TABLE_NAME='SYS10_DICTIONARY_VT' AND FIELD_NAME='DESCR_ID') >0
BEGIN
UPDATE SYS03_SEQUENCES SET CURRENT_VALUE = CURRENT_VALUE + INCREMENT_VALUE WHERE COMPANY_ID = @V_COMPANY_ID
AND SITE_ID =@V_SITE_ID AND TABLE_NAME = 'SYS10_DICTIONARY_VT' AND FIELD_NAME = 'DESCR_ID'
END

ELSE
IF @@ROWCOUNT =0 BEGIN
INSERT INTO SYS03_SEQUENCES(COMPANY_ID,
SITE_ID,
SNP_SITE_ID,
TABLE_NAME,
FIELD_NAME,
INITIAL_VALUE,
CURRENT_VALUE,
INCREMENT_VALUE,
USED)
VALUES (@V_COMPANY_ID,
@V_SITE_ID,
@V_SITE_ID,
'SYS10_DICTIONARY_VT',
'DESCR_ID',
9,
9,
10,
'Y');
SET @O_CURRENT_VALUE = 9;
END
SELECT @O_CURRENT_VALUE=CURRENT_VALUE FROM SYS03_SEQUENCES WHERE COMPANY_ID=@V_COMPANY_ID AND SITE_ID=@V_SITE_ID AND TABLE_NAME='SYS10_DICTIONARY_VT' AND FIELD_NAME='DESCR_ID'
-- raiserror

END


GO



tutto ciò non è stato creato appositamente per la tabella descritt, ma sia trigger che viste vengono creati dinamicamente attraverso l'esecuzione di una procedura scritta in t-sql lunga 500 righe, non mi sembra il caso di scriverla

lbenaglia Profilo | Guru

Manca la struttura della tabella SYS03_SEQUENCES ed i comandi di insert di test.

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

scandian Profilo | Newbie

SYS03:

CREATE TABLE [dbo].[SYS03_SEQUENCES] (
[COMPANY_ID] [char] (5) COLLATE Latin1_General_CI_AS NOT NULL ,
[SITE_ID] [numeric](5, 0) NOT NULL ,
[SNP_SITE_ID] [numeric](5, 0) NOT NULL ,
[TABLE_NAME] [varchar] (30) COLLATE Latin1_General_CI_AS NOT NULL ,
[FIELD_NAME] [varchar] (255) COLLATE Latin1_General_CI_AS NOT NULL ,
[INITIAL_VALUE] [numeric](8, 0) NULL ,
[CURRENT_VALUE] [numeric](15, 0) NULL ,
[INCREMENT_VALUE] [numeric](8, 0) NULL ,
[USED] [char] (1) COLLATE Latin1_General_CI_AS NOT NULL
) ON [PRIMARY]


GLI INSERT DI TEST LI HO FATTI DA ENTERPRICE MANAGER QUINDI DA INTERFACCIA GRAFICA

lbenaglia Profilo | Guru

>GLI INSERT DI TEST LI HO FATTI DA ENTERPRICE MANAGER QUINDI DA
>INTERFACCIA GRAFICA

Punto n.1: Non scrivere in maiuscolo che è segno di maleducazione;
punto n.2: Senza istruzioni di INSERT cosa possiamo verificare? Prepara una serie di INSERT (che inseriscono righe singole e righe multiple) e per ognuna di esse specifica il risultato che ti aspetteresti nelle 3 tabelle.

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

scandian Profilo | Newbie

un semplice esempio:



insert into ABC01_VT_FEATURES
(COMPANY_ID,SITE_ID,FEATURE_ID,
DESCR_ID,STATUS,TIMESTAMP,
USER_ID,CREATE_DATE,
USER_ID_CREATE,LAST_UPDATE,
USER_ID_UPDATE,ROW_VERSION,
TABLE_ID,DESCRIPTION,
LANGUAGE_ID_SYS10)
values
('PROVR',100,'BLABLABLA',1,'E',
0,'SCANDIAN',
GETDATE(),'SCANDIAN'
,GETDATE(),'SCANDIAN'
,0,'ABC01',
'BABABABABABA','IT')

avviene l'inserimento, ma poi non trovo nulla ne nella tabella ABC01_FEATURES ne nella SYS10

lbenaglia Profilo | Guru

>un semplice esempio:

Eseguendo quell'INSERT ottengo:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Come vedi il trigger è scattato, ha inserito una riga in abc01_features ma fallisce l'inserimento nella SYS10_DICTIONARY perché hai definito la colonna TIMESTAMP come NOT NULL ma il comando di INSERT del trigger non la contempla (e quindi cerca di valorizzarla a NULL):

INSERT INTO SYS10_DICTIONARY (COMPANY_ID,SITE_ID,DESCR_ID,LANGUAGE_ID,DESCRIPTION,USER_ID) VALUES(@COMPANY_ID,@SITE_ID,@DescrID2,@LANGUAGE_ID_SYS10,@DESCRIPTION,@USER_ID)

Dato che viene scatenata una eccezione l'intera transazione viene annullata e quindi non ti ritroverai nessuna riga in alcuna tabella.

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

scandian Profilo | Newbie

ho trovato l'errore...nel trigger di insert si fermava per colpa del rowcount....
ora funziona tutto.....
il problema è però che quando faccio insert nella vista, vuole per forza che specifichi tutti i campi, mentre io vorrei che fosse possibile lasciare certi a null, e lasciare che sia il trigger che si arrangi con la funzione isnull().

quando creo la vista è possibile settare che certi campi siano nullable???

lbenaglia Profilo | Guru

>ho trovato l'errore...nel trigger di insert si fermava per colpa
>del rowcount....

La tua vista deve essere diversa da quella che hai postato

>quando creo la vista è possibile settare che certi campi siano
>nullable???

Una vista è una SELECT memorizzata nel database. Non esiste uno schema come per le tabelle, quindi la domanda perde di significato.

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

scandian Profilo | Newbie

1) la vista è quella e anche il trigger, non è vero che avevo dichiarato not null lo status, infatti nel trigger utilizzavo la funzione isnull...
2)ci sarà un motivo per cui inserendo nella vista mi dice che non posso inserire a null certi campi....

lbenaglia Profilo | Guru

>1) la vista è quella e anche il trigger, non è vero che avevo
>dichiarato not null lo status, infatti nel trigger utilizzavo
>la funzione isnull...

Beh guarda, questo è quello che hai postato:

CREATE TABLE [dbo].[SYS10_DICTIONARY] (
[COMPANY_ID] [char] (5) COLLATE Latin1_General_CI_AS NOT NULL ,
[SITE_ID] [numeric](5, 0) NOT NULL ,
[LANGUAGE_ID] [varchar] (5) COLLATE Latin1_General_CI_AS NOT NULL ,
[DESCR_ID] [numeric](20, 0) NOT NULL ,
[DESCRIPTION] [varchar] (100) COLLATE Latin1_General_CI_AS NULL ,
[TIMESTAMP] [numeric](4, 0) NOT NULL ,
[USER_ID] [varchar] (20) COLLATE Latin1_General_CI_AS NOT NULL
) ON [PRIMARY]


Dimmi un po' se TIMESTAMP accetta o meno il valore NULL....

>2)ci sarà un motivo per cui inserendo nella vista mi dice che
>non posso inserire a null certi campi....

Appunto

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

scandian Profilo | Newbie

ok grazie, ho capito.....

però mi servirebbe un consiglio, a me servirebbe che la vista non erediti il NOT_NULL dalla tabella, ma che sia il trigger stesso a decidere cosa fare in caso di null, dato che l'inserimento non avviene direttamente dalla tabella, ma solo dalla vista.

sarebbe possibile creare la vista con alcuni campi che richiamano la funzione isnull(....)?
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