INSERT INTO动态添加列

Joh*_*hnZ 2 sql-server-2005 sql-server-2008

运行SQL Server 2005/2008,我正在重写我的查询更清洁,更符合不包括坏习惯.我曾经有很多IF陈述并且PIVOT要做到这一点,但现在找到了一种更好的方法来实现它,只需要最后一点就能使它几乎完美.

DECLARE @startdate DATETIME;
DECLARE @enddate DATETIME;
DECLARE @showstore INT;
DECLARE @showcashier INT;
DECLARE @showregister INT;
DECLARE @showdate INT;
DECLARE @sql NVARCHAR(MAX);
DECLARE @result0 NVARCHAR(MAX);

SET @startdate = '1/1/2012';
SET @enddate = '2/28/2013';
SET @showdate = 1;
SET @showstore = 0;
SET @showcashier = 1;
SET @showregister = 0;
SET @startdate = DATEADD(DAY, DATEDIFF(DAY, 0, @startdate), 0);
SET @enddate = DATEADD(DAY, DATEDIFF(DAY, 0, @enddate), 0);

SET @sql = N'CREATE TABLE ##a13 (' + SUBSTRING(
CASE WHEN @showdate = 1 THEN ',[Transaction Date] DATETIME' ELSE '' END + 
CASE WHEN @showstore = 1 THEN ',[Store ID] VARCHAR(10)' ELSE '' END + 
CASE WHEN @showcashier = 1 THEN ',[Cashier] VARCHAR(100)' ELSE '' END + 
CASE WHEN @showregister = 1 THEN ',[Register] VARCHAR(20)' ELSE '' END, 2, 2000);

DECLARE myCursor CURSOR FOR
    SELECT DISTINCT c.CurrencyDesc 
    FROM dbo.Currencies AS c INNER JOIN dbo.rpPay AS p ON c.POSCurrency = p.PayType 
        INNER JOIN dbo.RPTrs AS r ON r.ReceiptNO = p.ReceiptNo
    WHERE
        c.CurrencyDesc <> 'Testing' AND c.CurrencyDesc <> 'Cash Change' AND
        r.TRSDate >= @startdate AND r.TRSDate <= @enddate
OPEN myCursor
FETCH NEXT FROM myCursor INTO @result0
WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @sql = @sql + ',[' + @result0 + '] INT'
        FETCH NEXT FROM myCursor INTO @result0
    END
CLOSE myCursor
DEALLOCATE myCursor

SET @sql = @sql + ')'
EXECUTE sp_executesql @sql, N'@startdate DATETIME, 
    @enddate DATETIME',@startdate, @enddate;

SET @sql = 'SELECT * FROM ##a13; DROP TABLE ##a13'
EXECUTE sp_executesql @sql
Run Code Online (Sandbox Code Playgroud)

这将返回一个空行的表.(知道Currencies表有更多的CurrencyDesc然后在这里显示,因为这些只是在提供的日期范围内使用的)

在此输入图像描述

这正是我对它的期望.到目前为止很棒.现在我需要根据日期范围(@startdate >= and <= @enddate)向它添加数据行,具体取决于它们从4个可能的选项中检查的内容(@showstore, @showcashier, @showdate, @showregister)

示例:从2013年1月1日到2013年2月28日的日期和显示仅注册(如图所示)应具有此数据:

  | Register | Cash  | House Acct | MasterCard | Visa/MC
--------------------------------------------------------
1 | 01       | 20.00 | 235.25     | 1235.32    | 135.23
2 | 02       | 30.00 | 3542.42    | 323.52     | 523.64
3 | 03       | 23.35 | 100.32     | 3267.24    | 235.25
Run Code Online (Sandbox Code Playgroud)

2005/2008的原因是因为执行了一些客户端,仍然使用2005,为了使用PIVOT我将不得不改变2005年每个数据库的兼容级别.

PS.在我再次大喊大叫之前,如果我使用#a13而不是全局## a13,它会给我

Msg 208, Level 16, State 0, Line 1
Invalid object name '#a13'.
Run Code Online (Sandbox Code Playgroud)

我能做些什么,所以我不使用全局临时表?

JNK*_*JNK 6

如果我在这里不正确,请澄清.

我相信你会问如何根据用户输入使用动态列填充表格.这里正确的答案是,不要那样做!

这类事情的最佳做法是在输出表中包含所有字段,然后在应用程序/显示层中只显示用户请求的字段.

在TSQL中自定义表格布局只是为了进行干净的演示,这会带来许多不必要的复杂性.这种复杂性也会增加性能成本.

如果你有一个静态输出表,那么使用给定的参数返回数据是微不足道的.