【问题标题】:Dynamic SQL in Stored Procedure - Datetime parameters存储过程中的动态 SQL - 日期时间参数
【发布时间】:2010-12-29 12:11:10
【问题描述】:

得到一个正在转换为动态 SQL 的存储过程,原因是额外的 SQL 将在执行之前从外部系统传递到过程中。

从字符串转换日期时间时转换失败。 这是完整的存储过程:

USE [DBName];
GO
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
ALTER PROCEDURE [DB_Admin].[GetMiniCalendarDataNew]
@userID int, @startDate datetime, @endDate datetime, @JVID int = 0

WITH EXEC AS CALLER
AS

set nocount on

declare @SQLQuery AS NVARCHAR(max)

declare @t as table([day] int, [end] datetime, sortorder int, jv int)

SET @SQLQuery= 'insert into @t([day], [end], sortorder, jv)
select day((A.STARTTIME)) [day], max(a.endtime) ''end'', 3 sortorder,min(a.jv) jv 
from DB_Admin.CSTM_CALENDAR a
join DB_Admin.CSTM_CALENDAR b on a.id<>b.id
join DB_Admin.CSTM_CALENDARParticipants m1 on a.id=m1.CalendarID
join DB_Admin.CSTM_CALENDARParticipants m2 on b.id=m2.CalendarID
join DB_Admin.DTree DTree on a.FolderDataID=DTree.DataID
where a.starttime between ' + CAST(@startDate AS DATETIME) + ' AND ' + CAST(@endDate AS DATETIME) +
' AND DTree.OwnerID > 0
and b.starttime between ' + CAST(@startDate AS DATETIME) + ' AND ' + CAST(@endDate AS DATETIME) +
' AND a.starttime<b.endtime --find overlapping meetings
AND a.endtime>b.starttime --find overlapping meetings
AND M1.PARTICIPANT IN (
select id from DB_Admin.kuaf where id in (
    select id from DB_Admin.kuafchildren
    where childid=' +@userID+')
    or id=' +@userID+
')
AND M2.PARTICIPANT IN (
select id from DB_Admin.kuaf where id in (
    select id from DB_Admin.kuafchildren
    where childid='+@userID+') 
    or id='+@userID+
')'+

--Filter on JV
' AND ( exists (select 1 where a.jv='+@JVID+')
or    '+@JVID+'=0'+
')'+

'group by day(A.STARTTIME)'

+' insert into @t ([day], [end], sortorder, jv)
select day(A.STARTTIME) [day], max(a.endtime) ''end'', 2 SORTORDER,min(a.jv) jv
from DB_Admin.CSTM_CALENDAR a
join DB_Admin.CSTM_CALENDAR b on a.id<>b.id
join DB_Admin.CSTM_CALENDARParticipants m1 on a.id=m1.CalendarID
join DB_Admin.CSTM_CALENDARParticipants m2 on b.id=m2.CalendarID
join DB_Admin.DTree DTree on a.FolderDataID=DTree.DataID
where a.starttime between ' + CAST(@startDate AS DATETIME) +' AND ' +CAST(@endDate AS DATETIME)+
' AND DTree.OwnerID > 0
--Filter on JV
AND ( exists (select 1 where a.jv='+@JVID+')
or  '+@JVID+'=0'+')
and M1.PARTICIPANT IN (
select id from DB_Admin.kuaf where id in (
    select id from DB_Admin.kuafchildren
    where childid='+@userID+') 
    or id='+@userID+
')
group by (A.STARTTIME)'+

' insert into @t ([day], [end], sortorder, jv)
select day(A.STARTTIME) [day], max(a.endtime) ''end'', 1 SORTORDER,min(a.jv) jv
from DB_Admin.CSTM_CALENDAR a
join DB_Admin.CSTM_CALENDARParticipants m1 on a.ID=m1.CalendarID
join DB_Admin.DTree DTree on a.FolderDataID=DTree.DataID
where a.starttime between '+CAST(@startDate AS DATETIME)+' AND '+CAST(@endDate AS DATETIME)+
' AND DTree.OwnerID > 0
--Filter on JV
AND ( exists (select 1 where a.jv='+@JVID+')
or    '+@JVID+'=0'+ ')
and M1.PARTICIPANT NOT IN (
select id from DB_Admin.kuaf where id in (
    select id from DB_Admin.kuafchildren
    where childid='+@userID+') 
    or id='+@userID+'
)
group by (A.STARTTIME)'


--format query
+' select [day], max(month('+CAST(@startDate AS DATETIME)+' [month], max(year('+CAST(@endDate AS DATETIME)+')) [year], max([end]) ''end'', 
    case 
        when max(sortorder)=3 then ''Overlapping'' 
        when max(sortorder)=2 then ''Participating''
        when max(sortorder)=1 then ''Existing''
        when max(sortorder)=0 then ''Empty''

    end sortOrder , min(jv) JVID
from @t
group by [day]
order by sortorder desc'

--EXEC (@SQLQuery)

PRINT (@SQLQuery)

GO

【问题讨论】:

  • 对不起,这只是让我看着它流血。如果您希望人们提供帮助,您应该隔离导致错误的位,并对其进行格式化,使其更易于阅读。
  • 您需要先将日期转换为字符串,然后才能连接它们。

标签: sql stored-procedures dynamic-sql


【解决方案1】:

嗯,你需要

  • 引用它们
  • 确保它们是字符串
  • 让他们的语言/区域设置安全

所以:

...
where a.starttime between ''' + CONVERT(varchar(30), @startDate, 126) +''' AND ''' + ...
...

编辑:

int 错误。您需要 CAST @userID 以 varchar 连接它。 SQL 不做 VBA 风格的隐式 CAST

【讨论】:

  • 谢谢,我现在正在尝试这个转换建议。我的结果现在无法转换为 varchar。 "将 varchar 值 'insert 转换为 @t ([day], [end], sortorder, jv) select day((A.STARTTIME)) [day], max(a.endtime) 'end', 3 sortorder,min(a.jv) jv....."
  • 尝试 121 作为 ODBC 而不是 ISO 的格式。在执行之前还要打印字符串
  • 日期转换好像解决了。现在遇到 int 转换失败的问题: 将 varchar 值 'declare @t as table([day] int, [end] datetime ....." 转换为数据类型 int 时转换失败。将 datetime 参数临时替换为getdate 让它过去转换错误。
【解决方案2】:

我认为你的问题在这里:

'where a.starttime between ' + CAST(@startDate AS DATETIME) + ' AND ' + CAST(@endDate AS DATETIME) +

您应该将其转换为字符串,而不是日期时间。见http://msdn.microsoft.com/en-us/library/ms187928.aspx

【讨论】:

    猜你喜欢
    • 2021-07-28
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多