【问题标题】:Date and Table name as parameter in Dynamic SQL日期和表名作为动态 SQL 中的参数
【发布时间】:2014-07-31 16:06:18
【问题描述】:

我正在尝试创建一个存储过程,它允许我选择开始日期和结束日期以从中获取数据,并拥有一个变量表名来写入这些数据。

我想将两个日期和表名作为参数传入存储过程。这是我坚持的那部分。我拿出存储过程来尝试让它工作。这样我可以看到错误所在的行。

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;

我得到的错误是

从字符转换日期和/或时间时转换失败 字符串。

感谢您的帮助。

【问题讨论】:

    标签: sql sql-server variables stored-procedures dynamic


    【解决方案1】:

    您是否忘记将 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
    

    【讨论】:

    • 是的。这只是我的代码的一部分。它要长得多,但这就是我得到“从字符串转换日期和/或时间时转换失败”的地方。错误
    • 我没有收到那个错误。是在运行时还是在编译时?你在传递什么论点?
    • 我运行它的时候。我要过 2 个日期。 DECLARE @Start DATETIME SELECT @Start= DATEADD(WEEK, DATEDIFF(WEEK,0,GETDATE()), -7) DECLARE @End DATETIME SELECT @End= DATEADD(WEEK, DATEDIFF(WEEK,0,GETDATE()),0) EXECUTE SAN_Disk_Growth @Start,@End 这是我作为变量传入的内容
    • 没关系,我自己也很新。这里面的Date是什么?:CONVERT(VARCHAR(15),Date)如果是字段名,你可能需要括号[Date]。
    • 是的,它是一个日期时间字段,我试过括号,但没有运气。
    【解决方案2】:

    尝试将您的日期/时间值指定为动态 SQL 查询的参数。换句话说,不要将日期转换为 varchar,而是在查询中使用参数:

    WHERE @MaxDateWeek = V.Date;
    

    并将调用时的参数传递给 sp_executesql,如下所示:

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

    那么您就不必将日期转换为字符串。

    请注意,这不适用于动态表名或列名。这些需要连接在一起作为动态 SQL 本身的一部分。

    例如,如果你有一个像这样的表名变量:

    declare @TableName sysname
    set @TableName = 'MyTable'
    

    如果您希望动态 SQL 从该表中检索数据,那么您需要像这样构建您的 FROM 语句:

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

    这会将名称构建到 SQL 中,如下所示:

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

    【讨论】:

    • 我之前尝试过,但没有成功。我刚刚意识到我没有指定这个,但是我想要作为变量的表名在我的插入语句中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多