如何使用Python查询Wonderware的实时数值?

huangapple go评论65阅读模式
英文:

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])

huangapple
  • 本文由 发表于 2023年5月10日 20:19:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76218341.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定