我正在使用MS SQL通过链接服务器查询iHistorian。我想循环SQL表中的不同标记名。我遇到的问题是将参数添加到ihistorian查询中。代码如下。我没有在标记名中包含声明,因为此时它不相关。
SELECT timestamp AS Interval, Left(Right(TagName,Len(TagName)-5),Len(TagName)-10) as TagName,
CONVERT(decimal(10, 3), ROUND(value, 3)) As Value, quality
FROM
OPENQUERY(IHISTORIAN,'
SET starttime =''yesterday '', endtime =''yesterday +1h''
SELECT timestamp, tagname, value, ihRawData.quality
FROM ihRawData
WHERE tagname = '+ @tagname +'
AND timestamp BETWEEN ''timestamp'' and ''timestamp''
AND SamplingMode =Calculated
AND CalculationMode =Average
AND IntervalMilliseconds =1h
ORDER BY tagname, timestamp')
end
我遇到的问题是WHERE tagname = '+ @tagname +'
点。该查询不喜欢'+ @tagname +'
。它强调了第一个+
,并说预期会有)
。
我基本上想要独立于历史记录查询设置标记名,如前所述。
完整查询 -
use Optimiser_Test;
declare @tagname varchar(32)
--declare @rowcount int
--declare @maxrows int
--select @maxrows = count(*) from OptimiserTags
--set @rowcount = 0
set @tagname = 'UMIS.99FE1100.F_CV'
--while @rowcount < @maxrows
begin
SELECT timestamp AS Interval, Left(Right(TagName,Len(TagName)-5),Len(TagName)-10) as TagName,
CONVERT(decimal(10, 3), ROUND(value, 3)) As Value, quality
FROM
OPENQUERY(IHISTORIAN,'
SET starttime =''yesterday '', endtime =''yesterday +1h''
SELECT timestamp, tagname, value, ihRawData.quality
FROM ihRawData
WHERE tagname = REPLACE(@tagName, '''','')
AND timestamp BETWEEN ''timestamp'' and ''timestamp''
AND SamplingMode =Calculated
AND CalculationMode =Average
AND IntervalMilliseconds =1h
ORDER BY tagname, timestamp')
end
NEW UPDATE -
use Optimiser_Test;
declare @tagname varchar(32)
declare @fullquery varchar(1000)
set @fullquery = 'SELECT timestamp AS Interval, Left(Right(TagName,Len(TagName)-5),Len(TagName)-10) as TagName,
CONVERT(decimal(10, 3), ROUND(value, 3)) As Value, quality
FROM
OPENQUERY(IHISTORIAN,
SET starttime =''yesterday '', endtime =''yesterday +1h''
SELECT timestamp, tagname, value, ihRawData.quality
FROM ihRawData
WHERE tagname = '''+ @tagname +'''
AND timestamp BETWEEN ''timestamp'' and ''timestamp''
AND SamplingMode =Calculated
AND CalculationMode =Average
AND IntervalMilliseconds =1h
ORDER BY tagname, timestamp'''''
begin
set @tagname = 'UMIS.99FE1100.F_CV'
exec (@fullquery)
end
新更新2 -
如果我使用查询中指定的标记名运行查询,如下所示,我得到以下结果。这是正确的。
use Optimiser_Test;
SELECT timestamp AS Interval, Left(Right(TagName,Len(TagName)-5),Len(TagName)-10) as TagName,
CONVERT(decimal(10, 3), ROUND(value, 3)) As Value, quality
FROM
OPENQUERY(IHISTORIAN,'
SET starttime =''yesterday '', endtime =''yesterday +1h''
SELECT timestamp, tagname, value, ihRawData.quality
FROM ihRawData
WHERE tagname = UMIS.99FE1100.F_CV
AND timestamp BETWEEN ''timestamp'' and ''timestamp''
AND SamplingMode =Calculated
AND CalculationMode =Average
AND IntervalMilliseconds =1h
ORDER BY tagname, timestamp')
结果
经过与James S的多次来回和与我的同事的进一步合作之后,我得到了回报我需要的东西。
Declare @SQLString varchar(1000)
Declare @TAGS VarChar(1000)
Set @Tags = '"UMIS.99FE1100.F_CV"'
SET @SQLString = 'SELECT timestamp AS Interval, Left(Right(TagName,Len(TagName)-5),Len(TagName)-10) as TagName,
CONVERT(decimal(10, 3), ROUND(value, 3)) As Value, quality
FROM
OPENQUERY(IHISTORIAN,''
SET starttime =''''yesterday '''', endtime =''''yesterday +1h'''',
SELECT timestamp, tagname, value, ihRawData.quality
FROM ihRawData
WHERE tagname = ' + @Tags + '
and IntervalMilliseconds =1h,
and CalculationMode =Average,
and SamplingMode =Calculated
ORDER BY tagname, timestamp'')
'
Print @SQLString
Print @Tags
Exec (@SQLString)
答案 0 :(得分:1)
你的问题是缺少@tagname周围的引号(假设它是一个字符串) 但是我认为除了那个之外还有其他语法问题!
但是有没有理由使用OPENQUERY,而不是仅通过它的四个部分名称直接执行SQL引用源表:server.database.schema.table?
无论如何你应该换行:WHERE tagname = '+ @tagname +'
:WHERE tagname = '''+ @tagname +'''
以修复现有查询。
这当然是假设@tagName不是用户输入的,否则你会对SQL注入攻击持开放态度。您可以使用REPLACE(@tagName, '''','')
代替@tagName
来解决此问题,但直接查询会更加安全......
直接查询示例:
SET starttime ='yesterday', endtime ='yesterday +1h'
SELECT timestamp AS Interval,
Left(Right(TagName,Len(TagName)-5),Len(TagName)-10) as TagName,
CONVERT(decimal(10, 3), ROUND(value, 3)) As Value,
quality
FROM IHISTORIAN.<dbname>.dbo.ihRawData
WHERE tagname = @tagname
AND timestamp BETWEEN 'timestamp' and 'timestamp'
AND SamplingMode ='Calculated'
AND CalculationMode ='Average'
AND IntervalMilliseconds ='1h'
ORDER BY tagname, timestamp
修改强>
更正了OPENQUERY示例:(但不确定行SET starttime =''yesterday '', endtime =''yesterday +1h''
的用途是什么,所以这已被删除!)NB - 我假设SamplingMode,CalculationMode和IntervalMilliseconds应该是字符串,并将它们包含在转义引用中太。现在,整个SQL字符串首先构造成一个变量,然后再将其传递给OPENQUERY
use Optimiser_Test;
declare @tagname varchar(32)
DECLARE @startTimeStamp NVARCHAR(50), @endTimeStamp NVARCHAR(50)
DECLARE @sql NVARCHAR(8000)
--declare @rowcount int
--declare @maxrows int
--select @maxrows = count(*) from OptimiserTags
--set @rowcount = 0
set @tagname = 'UMIS.99FE1100.F_CV'
--while @rowcount < @maxrows
begin
SET @startTimeStamp = 'yesterday'
SET @endTimeStamp = 'yesterday +1h'
SET @sql = 'SELECT timestamp, tagname, value, ihRawData.quality
FROM ihRawData
WHERE tagname = ''' + REPLACE(@tagName, '''','') + '''
AND timestamp BETWEEN ''' + @startTimeStamp + '''
AND ''' + @endTimeStamp + '''
AND SamplingMode =''Calculated''
AND CalculationMode =''Average''
AND IntervalMilliseconds =''1h''
ORDER BY tagname, timestamp'
SELECT timestamp AS Interval, Left(Right(TagName,Len(TagName)-5),Len(TagName)-10) as TagName,
CONVERT(decimal(10, 3), ROUND(value, 3)) As Value, quality
FROM
OPENQUERY(IHISTORIAN, @sql)
end
编辑2
好的 - 如果您的最终查询得到了您想要的内容,那么您需要做的就是声明一个NVARCHAR变量 - 用SQL填充它,然后将该变量传递给openQuery。我不认为你可以在函数调用的()内动态构建字符串。
IE:
use Optimiser_Test;
declare @tagname varchar(32)
set @tagname = 'UMIS.99FE1100.F_CV'
DECLARE @SQL NVARCHAR(4000)
SET @SQL = 'SET starttime =''yesterday '', endtime =''yesterday +1h''
SELECT timestamp, tagname, value, ihRawData.quality
FROM ihRawData
WHERE tagname = ' + @tagname + '
AND timestamp BETWEEN ''timestamp'' and ''timestamp''
AND SamplingMode =Calculated
AND CalculationMode =Average
AND IntervalMilliseconds =1h
ORDER BY tagname, timestamp'
SELECT timestamp AS Interval, Left(Right(TagName,Len(TagName)-5),Len(TagName)-10) as TagName,
CONVERT(decimal(10, 3), ROUND(value, 3)) As Value, quality
FROM
OPENQUERY(IHISTORIAN,@SQL)