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

时间:2014-09-18 06:58:37

标签: tsql sql-server-2012 dynamic-sql create-table

我想创建一个包含Members_2014Spend_2014等列名的表格。我已经尝试将年份设置为变量并连接Member_ + @year,以便@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)

1 个答案:

答案 0 :(得分:1)

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

  • 您无法使用脚本重新创建过去两年前工作过的架构。
  • 您必须每年重写针对此数据库运行的所有查询和应用程序。

所以在短期内,您正在做的事情可能没问题,但最好简单地规范化您的架构并将年份作为额外的列:

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 sp_executesql system stored procedure可帮助您运行此类语句。