16

例として、最も単純なSQL関数を取り上げます。

CREATE OR REPLACE FUNCTION skater_name_match(INTEGER,VARCHAR)
RETURNS BOOL AS
$$
    SELECT $1 IN (SELECT skaters_skater.competitor_ptr_id FROM skaters_skater
    WHERE name||' '||surname ILIKE '%'||$2||'%' 
    OR surname||' '||name ILIKE '%'||$2||'%');
$$ LANGUAGE SQL;

これをコピーしてpsql(PostgreSQLのシェル)に貼り付けると、問題なく実行されます。

このようなPythonコードを(もちろん実際のデータベース名とユーザーを使用して)作成すると、次のようになります。

import psycopg2

sql_function_above = '''CREATE OR REPLACE FUNCTION skater_name_match(INTEGER,VARCHAR)
RETURNS BOOL AS
$$
    SELECT $1 IN (SELECT skaters_skater.competitor_ptr_id FROM skaters_skater
    WHERE name||' '||surname ILIKE '%'||$2||'%' 
    OR surname||' '||name ILIKE '%'||$2||'%');
$$ LANGUAGE SQL;'''

try:
    connection = psycopg2.connect("dbname='x' user='x' host='localhost' password='x'");
except:
    print "I am unable to connect to the database"

cursor = connection.cursor()
cursor.execute(sql_function_above)

実行されているように見えますが(エラーは発生しません)、データベースを調べたところ、関数がありません。

コードをapp/sql / model.sqlファイルに入れてDjangoで実行しようとすると、syncdb中に次のエラーが発生します。

IndexError: tuple index out of range

SQLを実行する独自のmanage.pyコマンドを作成しようとすると、同じエラーが発生します。

何が起きてる?これに光を当てることができた人にはとても感謝しています:)PythonとDjangoに関してはまだ初心者なので、明らかなことを見落としているかもしれません。

4

3 に答える 3

31

デフォルトでは、psycopg2は%記号を使用して引数のプレースホルダーを識別します(通常%sは文字列に含まれます)。

したがって、を使用するとcursor.execute('... %s, %s ...', (arg1, arg2))、それら%sはそれぞれarg1とarg2の値に変換されます。

しかし、cursor.execute(sql_function_above)追加の引数なしで:を呼び出し、SQLに%記号が含まれているため、ライブラリは関数に渡された2番目の引数を見つけようとしています。これは範囲外であるため、IndexErrorです。

解決策:を使用する代わりに、SQL変数%を書き込みます。これは、PostgreSQLに送信される前に%%リテラルに変換されます。%

于 2009-11-14T21:54:17.840 に答える
3

トランザクションをコミットしていないようです:

入れてみてください:

カーソル.execute("COMMIT")

最後の行の後、それが機能するかどうかを確認します。

次のように分離レベルを自動コミットに設定することもできます。

connection.set_isolation_level(0)

詳細については、この回答をご覧ください

于 2009-11-14T17:18:13.747 に答える