简体   繁体   English

日期和表名称作为Dynamic SQL中的参数

[英]Date and Table name as parameter in Dynamic SQL

I'm Trying to create a stored procedure that will allow me to pick a start date and end date to get data from and to have a variable table name to write this data to. 我正在尝试创建一个存储过程,该存储过程将允许我选择一个开始日期和结束日期以从中获取数据,并具有一个变量表名称来将该数据写入其中。

I would like to pass in the two dates and the table name as parameters in the stored procedure. 我想在存储过程中传递两个日期和表名作为参数。 Here is that part I'm stuck on. 这是我坚持的那一部分。 I took out the stored procedure to try and get this working. 我拿出存储过程来尝试使它正常工作。 this way I can see the lines the error is on. 这样,我可以看到错误所在的行。

DECLARE @MinDateWeek DATETIME
SELECT @MinDateWeek= DATEADD(WEEK, DATEDIFF(WEEK,0,GETDATE()), -7)
DECLARE @MaxDateWeek DATETIME
SELECT @MaxDateWeek= DATEADD(WEEK, DATEDIFF(WEEK,0,GETDATE()),0)
DECLARE @SQLCommand NVARCHAR(MAX)

    SET @SQLCommand = ' --ERROR ON THIS LINE
-- Getting how much space is used in the present
    DECLARE @Present Table (VMName NVARCHAR(50), UseSpace float(24))
    INSERT INTO @Present 
        SELECT  VMName
            ,SUM(CapacityGB-FreeSpaceGB)  
        FROM VMWareVMGuestDisk 

        GROUP BY VMName;
    -- Getting how much space was used at the reference date

    DECLARE @Past Table (VMName NVARCHAR(50), UseSpace float(24))
    INSERT INTO @Past
        SELECT  VMName
            ,SUM(CapacityGB-FreeSpaceGB)  
        FROM VMWareVMGuestDisk 
        WHERE Cast([Date] AS VARCHAR(20))= '''+CAST(@MinDateWeek AS varchar(20))+'''
        GROUP BY VMName;

    --Inserting the average growth(GB/DAY) between the 2 dates in a Temporary Table

    CREATE TABLE #TempWeek (VMName NVARCHAR(50) 
                    , CapacityGB float(24)
                    , GrowthLastMonthGB float(24)
                    , FreeSpace FLOAT(24) )

    INSERT INTO #TempWeek
    SELECT DISTINCT V.VMName
        ,SUM(V.CapacityGB)
        ,SUM(((W1.UseSpace-W2.UseSpace)/(DATEDIFF(DAY,'''+CONVERT(VARCHAR(50),@MaxDateWeek)+''','''+CONVERT(VARCHAR (50),@MaxDateWeek)+'''))))
        ,SUM(V.FreeSpaceGb)
    FROM VMWareVMGuestDisk AS V
        LEFT JOIN
        @Present AS W1
        ON
        V.VMName=W1.VMName
        LEFT JOIN
        @Past AS W2
        ON
        W1.VMName=W2.VMName
    WHERE (CONVERT(VARCHAR(15),Date))='''+CONVERT(VARCHAR(50),@MaxDateWeek)+'''
    GROUP BY V.VMName;

    -- Checking if there is already data in the table

            TRUNCATE TABLE SAN_Growth_Weekly;

    --insert data in permanent table
    INSERT INTO SAN_Growth_Weekly (VMName,Datacenter,Cluster,Company,DaysLeft,Growth,                                                             Capacity,FreeSpace,ReportDate)
        SELECT DISTINCT
            G.VMName
            ,V.Datacenter
            ,V.Cluster
            ,S.Company
            , DaysLeft = 
            CASE 
                WHEN G.GrowthLastMonthGB IS NULL 
                    THEN ''NO DATA''
                WHEN (G.GrowthLastMonthGB)<=0 
                    THEN ''UNKNOWN''
                WHEN (G.FreeSpace/G.GrowthLastMonthGB)>0 AND (G.FreeSpace/G.GrowthLastMonthGB) <=30 
                    THEN ''Less then 30 Days''
                WHEN (G.FreeSpace/G.GrowthLastMonthGB)>30 AND (G.FreeSpace/G.GrowthLastMonthGB)<=60                                 THEN ''Less then 60 Days''
                WHEN (G.FreeSpace/G.GrowthLastMonthGB)>60 AND (G.FreeSpace/G.GrowthLastMonthGB)<=90 
                    THEN ''Less then 90 Days''
                WHEN (G.FreeSpace/G.GrowthLastMonthGB)>90 AND (G.FreeSpace/G.GrowthLastMonthGB)<=180                                THEN ''Less then 180 Days''
                WHEN (G.FreeSpace/G.GrowthLastMonthGB)>180 AND (G.FreeSpace/G.GrowthLastMonthGB)<=365                               THEN ''Less then 1 Year''
                ELSE ''Over 1 Year''
            END
            ,G.GrowthLastMonthGB
            ,G.CapacityGB
            ,G.FreeSpace
            ,'''+@MaxDateWeek+'''
        FROM #tempWeek AS G
        RIGHT JOIN VMWareVMGuestDisk AS V
            ON V.VMName = G.VMName COLLATE SQL_Latin1_General_CP1_CI_AS
        LEFT JOIN Server_Reference AS S
            ON G.VMName COLLATE SQL_Latin1_General_CP1_CI_AS=S.[Asset Name]
        WHERE '''+CONVERT(VARCHAR(50),@MaxDateWeek)+'''= CONVERT(VARCHAR(50),V.Date);'

    EXEC sp_executesql @SQLCommand;

The error I get is 我得到的错误是

Conversion failed when converting date and/or time from character string. 从字符串转换日期和/或时间时转换失败。

Thanks for the help. 谢谢您的帮助。

Are you forgetting to enclose your Group By in the dynamic sql?: 您是否忘记将Group By包含在动态sql中?:

ALTER PROCEDURE SAN_DISK_GROWTH
    @MaxDateWeek DATETIME ,
    @MinDateWeek DATETIME
AS
    BEGIN
        DECLARE @SQLCommand NVARCHAR(MAX)
        SELECT  @SQLCommand = '
    DECLARE @Present Table (VMName NVARCHAR(50), UseSpace float(24))
    INSERT INTO @Present 
        SELECT  VMName
            ,SUM(CapacityGB - FreeSpaceGB)  
        FROM VMWareVMGuestDisk 
        WHERE CONVERT(VARCHAR(15),Date) = '''
                + CONVERT(VARCHAR(50), @MaxDateWeek) + ''' GROUP BY VMName;'

    END

Try specifying your date/time values as parameters to the dynamic SQL query. 尝试将日期/时间值指定为动态SQL查询的参数。 In other words, instead of converting the dates to a varchar, use parameters in the query: 换句话说,不是将日期转换为varchar,而是在查询中使用参数:

WHERE @MaxDateWeek = V.Date;

And pass the parameters on the call to sp_executesql like so: 并将参数传递给sp_executesql,如下所示:

EXEC sp_executesql @SQLCommand,
    '@MindateWeek datetime, @MaxDateWeek datetime',
    @MinDateWeek = @MinDateWeek,
    @MaxDateWeek = @MaxDateWeek

Then you won't have to convert your dates to strings. 然后,您将不必将日期转换为字符串。

Note that this does not work for dynamic table names or column names. 请注意,这不适用于动态表名或列名。 Those need to be concatenated together as part of the dynamic SQL itself. 那些需要作为动态SQL本身的一部分串联在一起。

For example, if you had a table name variable like this: 例如,如果您有一个像这样的表名变量:

declare @TableName sysname
set @TableName = 'MyTable'

And you wanted the dynamic SQL to retrieve data from that table, then you would need to build your FROM statement like this: 并且您希望动态SQL从该表中检索数据,那么您将需要像这样构建FROM语句:

set @SQLCommand = N'SELECT ...
    FROM ' + @TableName + N' WHERE...

This build the name into the SQL like so: 这样将名称构建到SQL中,如下所示:

'SELECT ... FROM MyTable WHERE...'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM