web-dev-qa-db-ja.com

MSSQL2008-Pyodbc-以前のSQLはクエリではなかった

次のコードの何が問題であるかを理解できません。構文IS ok(SQL Management Studioで確認)、私は必要に応じてアクセスできます。これも機能します。しかし、何らかの理由でPyODBCを介してテーブルを作成しようとするとすぐに機能しなくなります。

import pyodbc

def SQL(QUERY, target = '...', DB = '...'):
    cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=' + target + DB+';UID=user;PWD=pass')
    cursor = cnxn.cursor()
    cursor.execute(QUERY)
    cpn = []

    for row in cursor:
        cpn.append(row)
    return cpn

print SQL("CREATE TABLE dbo.Approvals (ID SMALLINT NOT NULL IDENTITY PRIMARY KEY, HostName char(120));")

それは失敗します:

Traceback (most recent call last):
  File "test_sql.py", line 25, in <module>
    print SQL("CREATE TABLE dbo.Approvals (ID SMALLINT NOT NULL IDENTITY PRIMARY KEY, HostName char(120));")
  File "test_sql.py", line 20, in SQL
    for row in cursor:
pyodbc.ProgrammingError: No results.  Previous SQL was not a query.

誰もがこれがなぜであるかについて何か考えがありますか? 「SQL Server」ドライバーがインストールされ(デフォルト)、Windows 7をWindows 2008 SQL Server環境(高速データベースではない)に対して実行しています。

27
Torxed

孤独なネット遊牧民がこの問題に遭遇した場合に備えて、Torxedによる解決策は私にはうまくいきませんでした。しかし、次のことがうまくいきました。

私はSPを呼び出し、テーブルにいくつかの値を挿入してからいくつかのデータを返しました。SPに以下を追加してください。

SET NOCOUNT ON

それはうまくいきます:)

Pythonコード:

    query = "exec dbo.get_process_id " + str(provider_id) + ", 0"
    cursor.execute(query)

    row = cursor.fetchone()
    process_id = row[0]

SP:

USE [DBNAME]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[GET_PROCESS_ID](
    @PROVIDER_ID INT,
    @PROCESS_ID INT OUTPUT
)
AS
BEGIN
    SET NOCOUNT ON
    INSERT INTO processes(provider_id) values(@PROVIDER_ID)
    SET @PROCESS_ID= SCOPE_IDENTITY()
    SELECT @PROCESS_ID AS PROCESS_ID
END
54
texens

これは、ループしていたカーソルを再利用していたためです。

rows = cursor.execute(...)
for row in rows:
    # run query that returns nothing
    cursor.execute(...)
    # next iteration of this loop will throw 'Previous SQL' error when it tries to fetch next row because we re-used the cursor with a query that returned nothing

代わりに2つの異なるカーソルを使用してください

rows = cursor1.execute(...)
for row in rows:
    cursor2.execute(...)

または、再度使用する前に、最初のカーソルのすべての結果を取得します。

代わりに2つの異なるカーソルを使用してください

rows = cursor.execute(...)
for row in list(rows):
    cursor.execute(...)
4
Matt

他の人がカバーしたように、SET NOCOUNT ONは、ストアドプロシージャ内の追加の結果セットを処理しますが、ストアドプロシージャのデバッグ後に印刷ステートメントを削除するのを忘れるなど、NOCOUNTが防止できない(そしてpyodbcが結果セットと見なされる)追加の出力を引き起こす可能性もあります。

3
Travis Truax

Travisや他の人が述べたように、SET NOCOUNT ONが妨げない余分な出力が他の原因でも発生する可能性があります。

手順の開始時にSET NOCOUNT ONを設定していましたが、結果セットに警告メッセージが表示されていました。

エラーメッセージを削除するために、スクリプトの最初にansi警告をオフに設定しました。

SET ANSI_WARNINGS OFF

うまくいけば、これは誰かを助けます。

1
Johnson

最初に:

windows SQL Server 2008を実行している場合は、SQLソフトウェアのインストールに含まれている「ネイティブクライアント」を使用します(データベースとツールキットとともにインストールされるため、MicrosoftのSQL管理アプリケーションをインストールする必要があります)

次に、SQL接続ステートメントで"Trusted_Connection = yes"を使用します。

cnxn = pyodbc.connect('DRIVER={SQL Server Native Client 10.0};SERVER=ServerAddress;DATABASE=my_db;Trusted_Connection=yes')

これでうまくいくはずです!

0
Torxed

SQLがストアドプロシージャでない場合。

クエリで 'xyz!= NULL'を使用すると、「pyodbc.ProgrammingError:No results。No results。Previous SQL was not a query」という同じエラーが発生します。

代わりに「is not null」を使用してください。

0
Mitendra