Tsql 如何使用动态列名(保存在变量中)创建表?

Tsql 如何使用动态列名(保存在变量中)创建表?,tsql,sql-server-2012,dynamic-sql,create-table,Tsql,Sql Server 2012,Dynamic Sql,Create Table,我想创建一个列名为Members\u 2014和Spend\u 2014的表。我尝试将年份设置为变量,并将成员+年份串联起来,这样@year将减少,但我编写的代码似乎不起作用: declare @li_year int declare @li_year2 int declare @li_year3 int declare @li_year4 int declare @li_year5 int set @li_year = datepart(year, GETDATE())

我想创建一个列名为
Members\u 2014
Spend\u 2014
的表。我尝试将年份设置为变量,并将
成员+年份
串联起来,这样
@year
将减少,但我编写的代码似乎不起作用:

declare @li_year    int
declare @li_year2   int
declare @li_year3   int
declare @li_year4   int
declare @li_year5   int

set @li_year = datepart(year, GETDATE())
set @li_year2 = @li_year-1
set @li_year3 = @li_year-2
set @li_year4 = @li_year-3
set @li_year5 = @li_year-4

drop table [scratchdb].[dbo].results_test
create table [scratchdb].[dbo].results_test (RDesc varchar(30), 
   'Members_' + @li_year int, 
   'Spend_' + @li_year money,
   'Members_' + @li_year2  int, 
   'Spend_' + @li_year2 money,
   'Members_' + @li_year3  int, 
   'Spend_' + @li_year3 money,
   'Members_' + @li_year4  int, 
   'Spend_' + @li_year4 money,
   'Members_' + @li_year5 int, 
   'Spend_' + @li_year5 money)

我想从个人观察开始:从长远来看,这很可能是个坏主意。理想情况下,数据库模式是固定的。但是,根据您运行脚本的年份,脚本将生成不同的数据库模式(如果它有效,也就是说)。这意味着,例如:

  • 您将无法使用您的脚本重新创建一个在一、两年前就可以使用的模式
  • 您必须每年重写针对该数据库运行的所有查询和应用程序
因此,在短期内,您所做的可能还可以,但最好只是规范化您的模式,并将年份作为一个附加列:

CREATE TABLE dbo.results_test
(
    RDesc   VARCHAR(30),
    Year    SMALLINT NOT NULL UNIQUE, -- UNIQUE to enforce at most one record per year
    Members INT,
    Spend   MONEY
);
如果您决定不这样做,并且支持当前的解决方案,那么您需要将整个SQL语句放在一个字符串变量中,而不仅仅是其中的一部分:

DECLARE @sql NVARCHAR(MAX) =
     'CREATE TABLE … Members_' + CAST(@li_year AS NVARCHAR) + ' INT, …' + …
--                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^       ^^^^
--                              regular string concatenation

EXECUTE sp_executesql @sql;

字符串变量中包含的SQL语句称为动态SQL,它可以帮助您运行这样的语句。

对于大多数查询处理,最好只使用固定的表名(例如第5年、第4年、第3年等)(现在您可能不需要全部使用动态SQL)然后只需将实际年份名称应用于您实际向用户提供数据的位置。谢谢您的建议。有道理。