2013-02-25 70 views
0

我需要將數據從非標準化數據庫導出到其中有多列到新的標準化數據庫。
一個示例是產品表,其中有30個布爾列(ValidSize1,ValidSize2 ecc ...),每個記錄都有一個外鍵,它指向一個大小表,其中有30列的大小代碼XS,S,M等)。爲了獲得產品的有效大小,只有在產品上的ValidSizeX爲真的情況下,我才必須掃描兩個表並從Sizes表中取得SizeCodeX的值。事情是這樣的:從非標準化數據庫導出數據

Products Table 
-------------- 
ProductCode <PK> 
Description 
SizesTableCode <FK> 
ValidSize1 
ValidSize2 
[...] 
ValidSize30 

Sizes Table 
----------- 
SizesTableCode <PK> 
SizeCode1 
SizeCode2 
[...] 
SizeCode30 

現在我使用的是「模板」查詢我重複30次:

SELECT 
    Products.Code, 
    Sizes.SizesTableCode, -- I need this code because different codes can have same size codes 
    Sizes.Size_1 
FROM Products 
INNER JOIN Sizes 
ON Sizes.SizesTableCode = Products.SizesTableCode 
WHERE Sizes.Size_1 IS NOT NULL 
AND Products.ValidSize_1 = 1 

我只是把這個查詢在一個循環中,我更換「_1 「與循環索引:

SET @counter = 1; 
SET @max  = 30; 
SET @sql  = ''; 

WHILE (@counter <= @max) 
BEGIN 
    SET @sql = @sql + ('[...]'); -- Here goes my query with dynamic indexes 

    IF @counter < @max 
     SET @sql = @sql + ' UNION '; 

    SET @counter = @counter + 1; 
END 

INSERT INTO DestDb.ProductsSizes EXEC(@sql); -- Insert statement 
GO 

是否有更好,更清潔或更快的方法來做到這一點?我正在使用SQL Server,我只能使用SQL/TSQL

謝謝!

+0

有沒有在你的模板查詢(4號線結束)流氓逗號。 – 2013-02-25 11:55:55

回答

0

您可以使用SYS.SYSCOLUMNS錶行獲得所有的價值

DECLARE @SqlStmt     Varchar(MAX) 
SET @SqlStmt='' 
SELECT @SqlStmt = @SqlStmt + 'SELECT '''+ name +''' column , UNION ALL ' 
FROM SYS.Syscolumns WITH (READUNCOMMITTED) 
WHERE Object_Id('dbo.Products')=Id AND ([Name] like 'SizeCode%' OR [Name] like 'ProductCode%') 

    IF REVERSE(@SqlStmt) LIKE REVERSE('UNION ALL ') + '%' 
    SET @SqlStmt = LEFT(@SqlStmt, LEN(@SqlStmt) - LEN('UNION ALL ')) 

    print (@SqlStmt) 
+0

我剛剛找到了一個不使用動態SQL的解決方案,速度非常快! – StockBreak 2013-02-25 14:26:01