none
Chiave esterna che punta a una sotto-stringa di una chiave primaria RRS feed

  • Domanda

  • Salve a tutti, 

    volevo chiedervi se era possibile creare una chiave esterna che punta alla sotto-stringa di una chiave primaria, io ho provato 

    con questo codice ma mi da errore:

    ALTER TABLE [dbo].[filbd]  WITH CHECK ADD  CONSTRAINT [FK_filbd_filtabel] FOREIGN KEY([tipo_prz1])
    REFERENCES [dbo].[filtabel] ([substring(cod_elemento,1,2)])
    GO
    
    ALTER TABLE [dbo].[filbd] CHECK CONSTRAINT [FK_filbd_filtabel]
    GO
    
    ora mi chiedevo se l'errore è causato perché tale operazione non è possibile, oppure ho sbagliato a scrivere il codice
    venerdì 15 novembre 2013 12:05

Risposte

  • salve,

    come hai visto, l'operazione non e' "direttamente" possibile, ma puoi molto facilmente aggirare il problema, anche se ti comporta "uno spreco di spazio" utilizzando una colonna calcolata.

    una colonna calcolata e' normalmente solo "un'espressione" basata su altre colonne, tipo "colonnaCalcolata AS colonna1 + colonna2" dichiarata nella definizione della creazione della tabella, e non occupa alcuno spazio fisico nella base dati in quanto viene risolta al momento della proiezione. Puoi utilizzare questa colonna calcolata, nel caso specifico "colonnaCalcolata AS SUBSTRING(cod_elemento, 1, 2)" anche per la gestione di constraint ed indici, ma in questo caso la colonna deve essere "serializzata", quindi occupera' spazio su disco e sara' fisicamente presente nel database....

    tipicamente scriverai qualche cosa simile a 

    SET NOCOUNT ON;
    USE tempdb;
    GO
    CREATE TABLE dbo.baseTB (
    	col char(2) PRIMARY KEY,
    	data varchar(5) NOT NULL
    	);
    CREATE TABLE dbo.referTB (
    	col int PRIMARY KEY,
    	col2 varchar(10) NULL,
    	colCalc AS CONVERT(CHAR(2), SUBSTRING(col2, 1, 2)) PERSISTED
    		CONSTRAINT fk_ferferTB$has$baseTB FOREIGN KEY
    			REFERENCES dbo.baseTB(col)
    	);
    GO
    INSERT INTO dbo.baseTB
    	VALUES ( 'ab', 'data1' ), ( 'cd', 'data2' );
    GO
    PRINT 'constraint soddisfatto';
    INSERT INTO dbo.referTB
    	VALUES ( 1, 'ab' ),
    		( 2 , 'cd' ),
    		( 3, NULL );
    GO
    PRINT 'constraint NON soddisfatto';
    INSERT INTO dbo.referTB
    	VALUES ( 4, 'ac' );
    GO
    SELECT r.*, b.data
    	FROM dbo.referTB r
    		LEFT JOIN dbo.baseTB b ON r.colCalc = b.col;
    GO
    DROP TABLE dbo.referTB, dbo.baseTB;
    --<--------
    constraint soddisfatto
    constraint NON soddisfatto
    Msg 547, Level 16, State 0, Line 2
    The INSERT statement conflicted with the FOREIGN KEY constraint "fk_ferferTB$has$baseTB". The conflict occurred in database "tempdb", table "dbo.baseTB", column 'col'.
    The statement has been terminated.
    col         col2       colCalc data
    ----------- ---------- ------- -----
    1           ab         ab      data1
    2           cd         cd      data2
    3           NULL       NULL    NULL
    

    che come vedi ti consente l'operazione DRI

    saluti


    http://www.hotelsole.com/asql/index.php - DbaMgr2k - DbaMgr and further SQL Tools http://www.hotelsole.com/

    sabato 16 novembre 2013 11:04
    Moderatore