问题描述
CREATE TABLE Tables2Create (
table_name nvarchar(256),colum_names nvarchar(max)
)
INSERT INTO Tables2Create VALUES ('People','Name|Occupation|Hobby')
INSERT INTO Tables2Create VALUES ('Schools','Name|Place|Type ')
现在我需要一些 Tsql,它会为字段 table_names 中的每个表动态创建表,并拆分字段 column_names 以决定每个表应该包含哪些列。所有字段都可以是 nvarchar 的。
CREATE TABLE People (
Name nvarchar(256),Occupation nvarchar(256),Hobby nvarchar(256)
)
知道怎么做吗?
解决方法
以下是使用 STRING_SPLIT
提取列名并使用 STRING_AGG
连接列名和 CREATE TABLE
语句的示例。
DECLARE @SQL nvarchar(MAX);
SELECT @SQL = STRING_AGG(CreateTableStatement,'')
FROM (
SELECT
'CREATE TABLE ' + QUOTENAME(table_name) + N' (' +
(
SELECT STRING_AGG(QUOTENAME(value) + ' nvarchar(256)',',')
FROM STRING_SPLIT(column_names,'|')
)
+ N');'
FROM dbo.Tables2Create
) AS CreateTableStatements(CreateTableStatement)
EXEC(@SQL);
,
你能做到吗?是的你可以。你应该?可能不会,如果我诚实的话。正如我在评论中提到的,存储分隔数据始终是一个设计缺陷;至少标准化你的设计。
话虽如此,我在这里使用的方法是“多合一”解决方案;没有游标,没有迭代。正如您标记了 SQL Server 2019,这意味着我们可以使用 STRING_AGG
。这给出了这样的东西:
USE master;
GO
CREATE DATABASE TestDB;
GO
USE TestDB;
GO
CREATE TABLE Tables2Create (table_name sysname,--correct data type for object names
column_names nvarchar(max)
)
INSERT INTO Tables2Create VALUES (N'People',N'Name|Occupation|Hobby')
INSERT INTO Tables2Create VALUES (N'Schools',N'Name|Place|Type ');
GO
DECLARE @SQL nvarchar(MAX),@CRLF nchar(2) = NCHAR(13) + NCHAR(10);
DECLARE @Delim nvarchar(10) = N',' + @CRLF + N' '
SET @SQL = (SELECT STRING_AGG(S.SQL,'')
FROM(SELECT @CRLF + @CRLF +
N'CREATE TABLE dbo.' + QUOTENAME(T2C.table_name) + N' (' + @CRLF + N' ' +
STRING_AGG(QUOTENAME(SS.value) + N' nvarchar(256)',@Delim) WITHIN GROUP (ORDER BY SS.[Value]) + @CRLF + N');' AS SQL
FROM dbo.Tables2Create T2C
CROSS APPLY STRING_SPLIT(T2C.column_names,N'|') SS
GROUP BY T2C.table_name) S);
PRINT @SQL; --Your best friend
EXEC sys.sp_executesql @SQL;
GO
USE master;
GO
DROP DATABASE TestDB;