英文:
How to query Wonderware live values with python?
问题
I'd like to query live tag value from Wonderware historian with python. The following sql query works inside SQL server management studio and returns the live value of the tag:
USE Runtime
DECLARE @TempTable TABLE(Seq INT IDENTITY, tempTagName NVARCHAR(256))
INSERT @TempTable(tempTagName) VALUES ('TAG_A')
SELECT v_Live.TagName, DateTime, vValue
FROM v_Live
LEFT JOIN @TempTable ON TagName = tempTagName
WHERE v_Live.TagName IN ('TAG_A')
ORDER BY Seq
However, I get the error 'Previous SQL was not a query' when I pass the query string above to 'cur.execute()'. I am using 'pyodbc' to connect to the SQL server.
with open_db_connection(server, database) as conn:
cur = conn.cursor()
query_string = textwrap.dedent("""USE Runtime
DECLARE @TempTable TABLE(Seq INT IDENTITY, tempTagName NVARCHAR(256))
INSERT @TempTable(tempTagName) VALUES ('TAG_A')
SELECT v_Live.TagName, DateTime, vValue
FROM v_Live
LEFT JOIN @TempTable ON TagName = tempTagName
WHERE v_Live.TagName IN ('TAG_A')
ORDER BY Seq
""")
cur.execute(query_string)
row = cur.fetchone()
print(row[1])
Anyone has an idea why I get this error and how can I solve it?
英文:
I'd like to query live tag value from Wonderware historian with python. The following sql query works inside SQL server management studio and returns the live value of the tag:
USE Runtime
DECLARE @TempTable TABLE(Seq INT IDENTITY, tempTagName NVARCHAR(256))
INSERT @TempTable(tempTagName) VALUES ('TAG_A')
SELECT v_Live.TagName, DateTime, vValue
FROM v_Live
LEFT JOIN @TempTable ON TagName = tempTagName
WHERE v_Live.TagName IN ('TAG_A')
ORDER BY Seq
However, I get the error Previous SQL was not a query
when I pass the query string above to cur.execute()
. I am using pyodbc
to connect to the SQL server.
with open_db_connection(server, database) as conn:
cur = conn.cursor()
query_string = textwrap.dedent("""USE Runtime
DECLARE @TempTable TABLE(Seq INT IDENTITY, tempTagName NVARCHAR(256))
INSERT @TempTable(tempTagName) VALUES ('TAG_A')
SELECT v_Live.TagName, DateTime, vValue
FROM v_Live
LEFT JOIN @TempTable ON TagName = tempTagName
WHERE v_Live.TagName IN ('TAG_A')
ORDER BY Seq
""")
cur.execute(query_string)
row = cur.fetchone()
print(row[1])
Anyone has an idea why I get this error and how can I solve it?
答案1
得分: 1
我认为 pyodbc
在执行多语句 SQL 脚本时存在问题,让我们尝试将它们拆分成多个语句然后分开执行。
编辑:表变量 @TempTable 的范围仅限于它声明的批处理,让我们使用全局临时表,不要忘记在之后删除全局临时表。
编辑2:在这种情况下,我们可以将所有 SQL 命令连接成一个单独的字符串,然后执行它,这可能会起作用。
with open_db_connection(server, database) as conn:
cur = conn.cursor()
query_string = """
USE Runtime;
DECLARE @TempTable TABLE(Seq INT IDENTITY, tempTagName NVARCHAR(256));
INSERT INTO @TempTable(tempTagName) VALUES ('TAG_A');
SELECT v_Live.TagName, DateTime, vValue
FROM v_Live
LEFT JOIN @TempTable ON TagName = tempTagName
WHERE v_Live.TagName IN ('TAG_A')
ORDER BY Seq;
"""
cur.execute(query_string)
row = cur.fetchone()
print(row[1])
英文:
I think pyodbc
have problem executing the multi-statement SQL script, lets try to split them into multiple statement then executing them separately.
edit: the scope of the table variable @TempTable is limited to the batch it was declared in, lets use global temp table, dont forget to drop the global temp table after
edit2: in this case we can concatenate all of your SQL commands into a single string then execute it, that might work.
with open_db_connection(server, database) as conn:
cur = conn.cursor()
query_string = """
USE Runtime;
DECLARE @TempTable TABLE(Seq INT IDENTITY, tempTagName NVARCHAR(256));
INSERT INTO @TempTable(tempTagName) VALUES ('TAG_A');
SELECT v_Live.TagName, DateTime, vValue
FROM v_Live
LEFT JOIN @TempTable ON TagName = tempTagName
WHERE v_Live.TagName IN ('TAG_A')
ORDER BY Seq;
"""
cur.execute(query_string)
row = cur.fetchone()
print(row[1])
答案2
得分: 0
以下是您要求的中文翻译部分:
1a: 摒弃临时表。它除了生成序列 ID 外没有任何作用。就您目前的问题而言,我不明白这样做有什么好处,反而增加了复杂性:
with open_db_connection(server, database) as conn:
cur = conn.cursor()
query_string = """
SELECT TagName, DateTime, vValue
FROM Runtime..v_Live
WHERE TagName IN ('TAG_A')
"""
cur.execute(query_string)
row = cur.fetchone()
print(row[1])
1b: 假设您要保留临时表,以下是使用 INNER REMOTE JOIN
语法的示例:
with open_db_connection(server, database) as conn:
cur = conn.cursor()
query_string = """
DECLARE @TempTable TABLE (
Seq INT IDENTITY,
tempTagName NVARCHAR(256)
);
INSERT INTO @TempTable (tempTagName) VALUES ('TAG_A');
SELECT v_Live.TagName, DateTime, vValue
FROM @TempTable
INNER REMOTE JOIN v_Live ON TagName = tempTagName
ORDER BY Seq;
"""
cur.execute(query_string)
row = cur.fetchone()
print(row[1])
2: 因为我不是 Python 开发者,所以我在询问是否可以使用存储过程来实现您的目标,因为您可以将 TSQL 包装在存储过程中来执行工作:
CREATE PROC QueryLiveData
@Tags nvarchar(max)
AS
SET NOCOUNT ON
DECLARE @TempTable TABLE (
Seq INT IDENTITY,
tempTagName NVARCHAR(256)
);
INSERT INTO @TempTable (tempTagName) VALUES (@Tags)
SELECT v_Live.TagName, DateTime, vValue
FROM @TempTable
INNER REMOTE JOIN v_Live ON TagName = tempTagName
ORDER BY Seq
GO
...或者如果需要传递多个标签,您可以使用逗号分隔,如 TAG_A,TAG_B,TAG_C
:
CREATE PROC QueryLiveData
@Tags nvarchar(max)
AS
SET NOCOUNT ON
DECLARE @TempTable TABLE (
Seq INT IDENTITY,
tempTagName NVARCHAR(256)
);
--将 @Tags 按逗号拆分并将各个值插入 @TempTable
WHILE LEN(@Tags) > 0 BEGIN
IF CHARINDEX(',', @Tags) > 0 BEGIN
INSERT INTO @TempTable
SELECT LEFT(@Tags, CHARINDEX(',', @Tags ) - 1)
SET @Tags = RIGHT(@Tags, LEN(@Tags) - CHARINDEX(',', @Tags))
END ELSE BEGIN
INSERT INTO @TempTable VALUES (@Tags)
SET @Tags = ''
END
END
SELECT v_Live.TagName, DateTime, vValue
FROM @TempTable
INNER REMOTE JOIN v_Live ON TagName = tempTagName
ORDER BY Seq
GO
然后对于您的 Python 代码(我假设您能够整理查询并在 Python 中使用正确的参数,而不是像我这样传递字符串):
with open_db_connection(server, database) as conn:
cur = conn.cursor()
query_string = """
EXEC RunTime..QueryLiveData 'TAG_A,TAG_B,TAG_C'
"""
cur.execute(query_string)
row = cur.fetchone()
print(row[1])
希望这些翻译能对您有所帮助。如果您需要更多信息或有其他疑问,请告诉我。
英文:
I'm going to leave an answer based on the comment I left on your original post, but I recommend making these changes:
1a: Do away with the temp table. It isn't doing anything for you besides generating a sequence ID. As your question stands right now, I don't see what benefit that has while generating more complexity:
with open_db_connection(server, database) as conn:
cur = conn.cursor()
query_string = """
SELECT TagName, DateTime, vValue
FROM Runtime..v_Live
WHERE TagName IN ('TAG_A')
"""
cur.execute(query_string)
row = cur.fetchone()
print(row[1])
1b: Assuming you're going to keep that temp table, here's syntax using INNER REMOTE JOIN
:
with open_db_connection(server, database) as conn:
cur = conn.cursor()
query_string = """
DECLARE @TempTable TABLE (
Seq INT IDENTITY,
tempTagName NVARCHAR(256)
);
INSERT INTO @TempTable (tempTagName) VALUES ('TAG_A');
SELECT v_Live.TagName, DateTime, vValue
FROM @TempTable
INNER REMOTE JOIN v_Live ON TagName = tempTagName
ORDER BY Seq;
"""
cur.execute(query_string)
row = cur.fetchone()
print(row[1])
2: Since I'm not a python dev, I was asking about using Stored Procs to achieve your ends because you could just wrap your TSQL in a proc to do the work:
CREATE PROC QueryLiveData
@Tags nvarchar(max)
AS
SET NOCOUNT ON
DECLARE @TempTable TABLE (
Seq INT IDENTITY,
tempTagName NVARCHAR(256)
);
INSERT INTO @TempTable (tempTagName) VALUES (@Tags)
SELECT v_Live.TagName, DateTime, vValue
FROM @TempTable
INNER REMOTE JOIN v_Live ON TagName = tempTagName
ORDER BY Seq
GO
...or alternatively if you need to pass multiple tags you can comma separate them like TAG_A,TAG_B,TAG_C
:
CREATE PROC QueryLiveData
@Tags nvarchar(max)
AS
SET NOCOUNT ON
DECLARE @TempTable TABLE (
Seq INT IDENTITY,
tempTagName NVARCHAR(256)
);
--Splits the @Tags on comma and inserts individual values to @TempTable
WHILE LEN(@Tags) > 0 BEGIN
IF CHARINDEX(',', @Tags) > 0 BEGIN
INSERT INTO @TempTable
SELECT LEFT(@Tags, CHARINDEX(',', @Tags ) - 1)
SET @Tags = RIGHT(@Tags, LEN(@Tags) - CHARINDEX(',', @Tags))
END ELSE BEGIN
INSERT INTO @TempTable VALUES (@Tags)
SET @Tags = ''
END
END
SELECT v_Live.TagName, DateTime, vValue
FROM @TempTable
INNER REMOTE JOIN v_Live ON TagName = tempTagName
ORDER BY Seq
GO
Then for your python (I'm assuming you'd be able to clean up the query and use proper params in Python instead of a string passed like I have):
with open_db_connection(server, database) as conn:
cur = conn.cursor()
query_string = """
EXEC RunTime..QueryLiveData 'TAG_A,TAG_B,TAG_C'
"""
cur.execute(query_string)
row = cur.fetchone()
print(row[1])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论