web-dev-qa-db-ja.com

ビューからSQLテーブルDDLを生成する

1つのスクリプトでビューからテーブル構造を生成するにはどうすればよいですか?必要なのはデータ型のみです。あるタイプの動的SQLを含むテーブル作成スクリプトを探しています。

(1)主キー/制約を削除できる、

(2)null/not nullが追加されているかどうかは気にしない(ただし、持っていると便利です)

以下のサンプルの質問/回答を提案しました。コードレビューを自由に行ってください。今後、表に含まれていない他のデータタイプを編集/最適化します。特殊なケース/問題/例外が考慮されていない場合があります。ところで、このためのオープンソースコードはありますか?

表1および2:

create table dbo.Customer
(
     CustomerId int primary key,
     CustomerName varchar(255),
     ZipCode varchar(9)
)
create table dbo.CustomerTransaction
(
     CustomerTransactionId int primary key identity(1,1),
     CustomerId int,
     SalesAmount numeric (10,2),
     PurchaseDate datetime
)

ビュー:

create view dbo.CustomerTransactionVw
as
select 
     ct.CustomerTransactionId,
     ct.SalesAmount,
     ct.PurchaseDate,
     cust.CustomerId,
     CustomerName,
     cust.ZipCode
from dbo.CustomerTransaction ct
inner join dbo.Customer cust
  on cust.CustomerId = ct.CustomerId

目的のテーブル作成スクリプト:

create table dbo.CustomerTransactionBigTable
(
     CustomerTransactionId int identity(1,1),
     CustomerId int,
     SalesAmount numeric (10,2),
     PurchaseDate datetime,
     CustomerId int,
     CustomerName varchar(255),
     ZipCode varchar(9)
)

現在提案されているソリューション:

declare @TableCode varchar(max) = 'create table dbo.CustomerLargeTable 
( ' + 
    (select STUFF((
    SELECT ', 
    '    
    + c.name + ' ' + 
case 
    when t.name like '%char%' then t.name + '(' + cast(c.max_length as varchar(10)) + ')' 
    when t.name like '%numeric%' or t.name like '%decimal%' then t.name + '(' + cast(c.precision as varchar(10)) + ',' + cast(c.scale as varchar(10)) + ')'
    else t.name
end
FROM .sys.columns c 
inner JOIN sys.types t
    on t.user_type_id = c.user_type_id
    and t.system_type_id = c.system_type_id
where c.object_id = object_id('CustomerTransactionVw') and is_identity = 0
FOR XML PATH(''), TYPE).value('.','nvarchar(max)'),1,2,''))
+ '
)'  

print @TableCode

注:データDMLではなく、テーブル構造DDLのみに関心があります

https://stackoverflow.com/questions/7254380/how-to-find-the-derived-column-types-of-a-view-in-sql-server-2005

2
user162241

質問タグにSQL Server 2016と記載されているため、SQL Server 2012で使用可能になった sys.dm_exec_describe_first_result_set を利用できます。

この動的管理関数は、Transact-SQLステートメントをパラメーターとして取り、ステートメントの最初の結果セットのメタデータを記述します。

--Demo set up
DROP TABLE IF EXISTS [dbo].[Customers]
CREATE TABLE [dbo].[Customers](
    [CustomerID] [nchar](5) NOT NULL,
    [CompanyName] [nvarchar](40) NOT NULL,
    [ContactName] [nvarchar](30) NULL,
    [ContactTitle] [nvarchar](30) NULL,
    [Address] [nvarchar](60) NULL,
    [City] [nvarchar](15) NULL,
    [Region] [nvarchar](15) NULL,
    [PostalCode] [nvarchar](10) NULL,
    [Country] [nvarchar](15) NULL,
    [Phone] [nvarchar](24) NULL,
    [Fax] [nvarchar](24) NULL
) ON [PRIMARY]
GO

DROP VIEW IF EXISTS CustomerView 
GO
CREATE VIEW CustomerView
AS
SELECT *
FROM dbo.Customers
GO

-------------------------------
--The solution    
SET NOCOUNT ON;

DECLARE @sql NVARCHAR(MAX)
    ,@cols NVARCHAR(MAX) = N'';

SELECT @cols += N',' + NAME + ' ' + system_type_name
FROM sys.dm_exec_describe_first_result_set(N'SELECT * FROM dbo.CustomerView', NULL, 1);

SET @cols = STUFF(@cols, 1, 1, N'');
SET @sql = N'CREATE TABLE #tmp(' + @cols + ');'
SET @sql = replace(@sql,',',',' + char(10))
print @sql

結果:

CREATE TABLE #tmp(CustomerID nchar(5),
CompanyName nvarchar(40),
ContactName nvarchar(30),
ContactTitle nvarchar(30),
Address nvarchar(60),
City nvarchar(15),
Region nvarchar(15),
PostalCode nvarchar(10),
Country nvarchar(15),
Phone nvarchar(24),
Fax nvarchar(24));
5
Scott Hodgin

SELECT INTO を使用します。

SELECT TOP 0 *
INTO #SomeNewTable
FROM [SomeDB].[SomeSchema].[SomeView]

上記は、ソースビューと同じ構造の新しいテーブルを作成します。

3
George.Palacios