2013-01-09 51 views
0

我正在尋找一種方法來爲一堆表自動創建每個表的1:1視圖。 由於有很多表需要查看,因此手動創建它們會非常耗時。自動爲一堆表創建視圖

完美的場景是查詢爲一次給定的每個表創建create view查詢。

+0

你到目前爲止試過了什麼?您可以查詢[sys.tables](http://msdn.microsoft.com/en-us/library/ms187406(v = sql.100).aspx)和[sys.columns](http://msdn.microsoft .com/en-us/library/ms176106(v = sql.100).aspx)來獲取你需要的名字;這有幫助嗎? – Pondlife

+0

是的。我看看這個創建的動態SQL來創建視圖。希望有一個更「優雅」的解決方案! – Nico

+0

「優雅」是什麼意思?無論您選擇哪種解決方案,您都需要檢索表名和列名,並構建「CREATE VIEW」語句。所以唯一的問題是,你是使用TSQL還是使用外部代碼(可能使用SMO)? – Pondlife

回答

1

這應該對當前數據庫有用。它仍然是動態SQL,但是...請注意,它不檢查視圖是否已經存在。您可以將光標查詢添加WHERE子句以限制表格 - WHERE t.name = '...'WHERE t.name IN ('...','....')

DECLARE @TableName sysname 
DECLARE @ColumnCount INT 
DECLARE @ColumnID INT 
DECLARE @SelectColumn NVARCHAR(500) 
DECLARE @sql NVARCHAR(max) = '' 

DECLARE QUERYINFO CURSOR FOR 
    SELECT 
     t.name AS TableName, 
     ccount.ColumnCount, 
     c.column_id AS ColumnID, 
     CASE WHEN c.column_id <> ccount.ColumnCount 
       THEN c.name + ', ' 
      ELSE c.name 
      END AS SelectColumn 
    FROM sys.tables t 
    INNER JOIN sys.columns c ON t.object_id=c.object_id 
    INNER JOIN (
     SELECT object_id,COUNT(*) AS ColumnCount 
     FROM sys.columns 
     GROUP BY object_id 
    ) ccount ON t.object_id = ccount.object_id 
    ORDER BY t.Name,c.column_id 

OPEN QUERYINFO 
FETCH NEXT FROM QUERYINFO INTO @TableName,@ColumnCount,@ColumnID,@SelectColumn 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    IF @ColumnID = 1 
    BEGIN 
     SET @sql = 'CREATE VIEW v_' + @TableName + ' AS SELECT ' + @SelectColumn 
    END 
    ELSE 
    BEGIN 
     SET @sql = @sql + @SelectColumn 
    END 

    IF @ColumnID = @ColumnCount 
    BEGIN 
     SET @sql = @sql + ' FROM ' + @TableName 
     EXEC sys.sp_executesql @sql 
     SET @sql = '' 
    END 

    FETCH NEXT FROM QUERYINFO INTO @TableName,@ColumnCount,@ColumnID,@SelectColumn 
END 

CLOSE QUERYINFO 
DEALLOCATE QUERYINFO 
+0

只需謹慎一點 - 子句IF \ @ColumnID = \ @ColumnCount可能無法按預期工作,因爲ColumnID可能不是按順序的 - 即在刪除列(除最後一列之外)後,ID不會重新編號。 – Rashack

0

我知道這是一個有點過時,但你可以使用一個臨時表遞歸CTE串起來,從SYS.COLUMNS和SYS.TABLES列,然後生成視圖不使用過程或遊標。這是一個例子。這個只會選擇一個object_id,但是你可以爲你的db中的所有表運行它。唯一的問題可能是如果你有一個大於100列的表。我認爲CTE的默認深度是100個遞歸連接。

SELECT t.name AS TableName 
     , ccount.ROW_COUNT 
     , c.column_id AS ROW_RANK 
     , c.name as COL 

INTO #VT_TEMP 

FROM sys.tables t INNER JOIN sys.columns c 
ON t.object_id=c.object_id 

INNER JOIN ( SELECT object_id 
        , COUNT(*) AS ROW_COUNT 
       FROM sys.columns 
       GROUP BY object_id 
    ) ccount 
ON t.object_id = ccount.object_id 
WHERE t.OBJECT_ID = 245575913 
ORDER BY t.Name, c.COLUMN_ID 
; 



WITH MYVIEW_CTE (T_NAME, R_COUNT, R_RANK, TXT) 

AS 
    (
    SELECT TABLENAME 
     , ROW_COUNT 
     , ROW_RANK 
     , CAST(COL AS VARCHAR(MAX)) 

    FROM #VT_TEMP 
    WHERE ROW_RANK = 1 

    UNION ALL 

    SELECT V.TABLENAME 
      , V.ROW_COUNT 
      , V.ROW_RANK 
      , CAST(TXT + ', ' + V.COL AS VARCHAR(MAX)) 


    FROM #VT_TEMP V INNER JOIN MYVIEW_CTE C 
    ON V.TABLENAME = T_NAME 
    AND V.ROW_RANK = R_RANK + 1 
) 

SELECT CC.T_NAME 
     ,CC.TXT 
     , 'CREATE VIEW V_' + CC.T_NAME + ' AS SELECT ' + CC.TXT + ' FROM dbo.' + CC.T_NAME + ' ;' as DDL_View 
FROM MYVIEW_CTE CC INNER JOIN (

SELECT T_NAME, MAX(R_RANK) AS MX_CNT 
FROM MYVIEW_CTE C 
GROUP BY T_NAME 
) SC 
ON CC.T_NAME = SC.T_NAME 
AND CC.R_RANK = SC.MX_CNT