salve,
ALonE75 ha scritto:
Ciao a tutti
ho una tabella in cui ho un campo in cui inserisco separati da virgola gli ID di record di un'altra tabella..
e' una "normalizzazione pessima"

e non ce'e' bisogno che te lo dica.. il disegno architetturale sarebbe sicuramente da ridisegnare, ma tant'e'..
Vista
------------------------------------------------
TAB1_ID | Campo | Descrizione |
------------------------------------------------
1 | Valore1 | Testo1,Testo2 |
2 | Valore2 | Testo1,Testo3,Testo4 |
3 | Valore3 | Testo2,Testo4 |
------------------------------------------------[/code]
Ho provato a fare delle accrobazie con SQL ma senza risultati...
Un aiutino?
Gracias
il motivo e' ppiu' che semplice, (e mi ripeto) la normalizzazione e' piu' che pessima

...
con SQL Server, tutte le edizioni, con una vista non lo puoi fare, visto che ti devi basare su una "aggregazione di concatenazione" supportata dalle "stringhe", cioe' i tipi di dati char/varchar..
puoi infatti concatenare un risultato intermedio tipo
DECLARE @Result varchar(n);
SET @Result = '';
SELECT @Result = @Result + <colonna> FROM ...
chiaramente devi necessariamente rientrare nel limite del tipo di dato, con SQL Server 2000 ad esempio il limite e' 8000 caratteri per varchar, cosa che potrebbe avere serie problematiche..
di seguito un esempio che utilizza una stored procedure per il ritorno di una unica riga tipo
2 | Valore2 | Testo1,Testo3,Testo4 |
passando come parametro alla stessa il valore della colonna in chiave primaria (nel caso specifico probabilmente Tab1_Id), ed anche un altro esempio che utilizza una funzione definita dall'utente (disponibile solo a partire da SQL Server 2000) basata sullo stesso principio, ma che invece ritorna l'intero set richiesto da proiezione della tabella principale Table1..
mi spiace che il post non manterra' la formattazione del codice, cosa che probabilmente lo rendera' poco leggibile..
a prescindere da cio' il punto fondamentale e' un ciclo appunto su "1,2,n" che prende ogni elemento del multi-attributo e lo utilizza vuoi per un inserimento in una tabella temporanea della quale poi effettuare una JOIN ovvero, nel caso della funzione, di solo caricamento della aggregazione concatenata..
SET NOCOUNT ON;
USE tempdb;
GO
CREATE TABLE dbo.Table1 (
Tab1_ID int NOT NULL ,
Campo varchar(10) NOT NULL, -- Campo?? rotfl
Tab2_ID varchar(50) NOT NULL
);
CREATE TABLE dbo.Table2 (
Tab2_ID int NOT NULL ,
Descrizione varchar(10) NOT NULL
);
GO
INSERT INTO dbo.Table1 VALUES ( 1 , 'Valore 1', '1,2' );
INSERT INTO dbo.Table1 VALUES ( 2 , 'Valore 2', '1,3,4' );
INSERT INTO dbo.Table1 VALUES ( 3 , 'Valore 3', '2,4' );
INSERT INTO dbo.Table1 VALUES ( 4 , 'Valore 4', '' );
INSERT INTO dbo.Table2 VALUES ( 1 , 'Testo 1' );
INSERT INTO dbo.Table2 VALUES ( 2 , 'Testo 2' );
INSERT INTO dbo.Table2 VALUES ( 3 , 'Testo 3' );
INSERT INTO dbo.Table2 VALUES ( 4 , 'Testo 4' );
GO
CREATE PROCEDURE dbo.usp_GetValues (
@Id int
)
AS BEGIN
SET NOCOUNT ON;
CREATE TABLE #temp ( Id int NOT NULL, Tab1_ID int NOT NULL );
DECLARE @Refer varchar(50);
DECLARE @Pos int;
SELECT @Refer = Tab2_ID FROM dbo.Table1 WHERE Tab1_ID = @id;
IF NOT @Refer IS NULL BEGIN
WHILE DATALENGTH(@Refer) <> 0 BEGIN
SELECT @Pos = CHARINDEX(',', @Refer);
IF @Pos <> 0 BEGIN
INSERT INTO #temp VALUES ( CONVERT( int, SUBSTRING (@Refer, 0 , @Pos)), @id );
SET @Refer = SUBSTRING (@Refer, @Pos + 1 , DATALENGTH(@Refer) - @Pos);
END;
ELSE BEGIN
INSERT INTO #temp VALUES (CONVERT( int, @Refer ), @id);
SET @Refer = ''
END;
END;
END;
DECLARE @Result varchar(100);
SET @Result = '';
SELECT @Result = @Result + CASE WHEN DATALENGTH(@Result) <> 0 THEN ', ' ELSE '' END + t2.Descrizione
FROM #temp t
JOIN dbo.Table2 t2 ON t2.Tab2_ID = t.ID;
DROP TABLE #temp;
SELECT t1.Tab1_ID, t1.Campo, @Result AS [Descrizione]
FROM dbo.Table1 t1
WHERE t1.Tab1_ID = @Id;
END;
GO
EXEC dbo.usp_GetValues 1;
EXEC dbo.usp_GetValues 2;
EXEC dbo.usp_GetValues 3;
EXEC dbo.usp_GetValues 4;
GO
CREATE FUNCTION dbo.ufn_GetValues (
@Id int
) RETURNS varchar(100)
AS BEGIN
DECLARE @Refer varchar(50);
DECLARE @Pos int;
SELECT @Refer = Tab2_ID FROM dbo.Table1 WHERE Tab1_ID = @id;
DECLARE @Result varchar(100);
SET @Result = '';
IF NOT @Refer IS NULL BEGIN
WHILE DATALENGTH(@Refer) <> 0 BEGIN
SELECT @Pos = CHARINDEX(',', @Refer);
IF @Pos <> 0 BEGIN
SELECT @Result = @Result + CASE WHEN DATALENGTH(@Result) <> 0 THEN ', ' ELSE '' END + t2.Descrizione
FROM dbo.Table2 t2 WHERE t2.Tab2_ID = CONVERT( int, SUBSTRING (@Refer, 0 , @Pos));
SET @Refer = SUBSTRING (@Refer, @Pos + 1 , DATALENGTH(@Refer) - @Pos);
END;
ELSE BEGIN
SELECT @Result = @Result + CASE WHEN DATALENGTH(@Result) <> 0 THEN ', ' ELSE '' END + t2.Descrizione
FROM dbo.Table2 t2 WHERE t2.Tab2_ID = CONVERT( int, @Refer);
SET @Refer = ''
END;
END;
END;
RETURN (@Result);
END;
GO
SELECT t1.Tab1_ID, t1.Campo, dbo.ufn_GetValues (t1.Tab1_ID) AS [Descrizione]
FROM dbo.Table1 t1;
GO
DROP FUNCTION dbo.ufn_GetValues ;
DROP PROCEDURE dbo.usp_GetValues ;
DROP TABLE dbo.Table2, dbo.Table1 ;
il risultato della chiamata a
EXEC dbo.usp_GetValues n;
e' simile a
Tab1_ID Campo Descrizione
----------- ---------- -----------------
3 Valore 3 Testo 2, Testo 4
dove invece l'utilizzo della funzione ritorna
Tab1_ID Campo Descrizione
----------- ---------- --------------------------
1 Valore 1 Testo 1, Testo 2
2 Valore 2 Testo 1, Testo 3, Testo 4
3 Valore 3 Testo 2, Testo 4
4 Valore 4
a meno di non filtrare
SELECT t1.Tab1_ID, t1.Campo, dbo.ufn_GetValues (t1.Tab1_ID) AS [Descrizione] FROM dbo.Table1 t1 WHERE ......;
cio' non toglie che, ripeto ancora, trattasi di una "normalizzazione pessima"
saluti