我有一个本地存储过程,在远程链接服务器上调用另一个。问题是我的本地存储过程使用openquery
来调用远程存储过程并传递两个DATETIME
参数。
我能成功调用远程存储过程的唯一方法是连接查询及其参数,然后使用sp_executesql
- 注意远程服务器上没有启用RPC,这只限制了成功的方法。
问题是连接日期时间以便将它们作为变量传递会导致远程proc中出现问题,而远程proc期望datetime
参数不是nvarchar
,这就是串联正在进行的操作。
这有什么办法吗?最后一种方法是修改远程proc并让它接受nvarchar
,然后立即将它们转换为datetime
。这不是一种可行的方法,因为远程过程在其他系统中使用。
本地SP
ALTER PROCEDURE [dbo].[GetAttendanceReport]
@StartDate datetime,
@EndDate datetime,
@paramDef nvarchar(500) = N'@StartDate datetime, @EndDate datetime',
@query nvarchar(500) = null
AS
BEGIN
SET NOCOUNT ON;
set @query = N'select * from OPENQUERY([REMOTE-SRV], ''EXEC db.dbo.ReportAttendance_sp ' + convert(nvarchar(30), @StartDate, 112) + ',' + convert(nvarchar(30), @EndDate, 112) + ''')'
exec sp_executesql @query, @paramDef, @StartDate, @EndDate
END
远程SP
ALTER PROCEDURE [dbo].[ReportAttendance_sp]
@VenueID int = null,
@StartDate datetime = null,
@EndDate datetime = null,
@AttendanceStatusID int = null
AS
BEGIN
...
我通过以下参数:
@StartDate = N'2011-01-01',
@EndDate = N'2012-01-01'
执行SP我从远程SP获取错误:
将数据类型int转换为datetime时出错。
答案 0 :(得分:1)
你需要传递那些连接的参数,就好像它们是字符串一样。目前,它们看起来像int,正如错误消息所暗示的那样 - 您需要将单引号加倍,将它们嵌入为字符串分隔符,然后再次,因为它们位于动态SQL中。此外,没有理由专门为这些文字使用NVARCHAR,也不需要30个字符来表示样式112.您只需要使用CHAR(8)。最后,如果您实际上没有将任何参数用作强类型参数(我认为您不能将它与动态SQL下的OPENQUERY结合使用),则无需将参数传递给sp_executesql
。所以:
SET @query = N'SELECT * from OPENQUERY([REMOTE-SRV],
''EXEC db.dbo.ReportAttendance_sp ''''' + convert(char(8), @StartDate, 112)
+ ''''',''''' + convert(char(8), @EndDate, 112) + ''''';'');';
EXEC sp_executesql @sql;
(当然,你真的应该明确地命名这些参数,这至少可以保护你免受以后改变界面的人的影响,例如通过在参数列表的开头添加一个参数。)
然而,这引出了一个问题,为什么不解决RPC问题然后:
EXEC [REMOTE-SRV].db.dbo.ReportAttendance_sp @StartDate, @EndDate;