为什么psycopg2不执行我的任何SQL函数?(IndexError:元组索引超出范围)

Mon*_*lik 16 python sql django postgresql psycopg2

我将以最简单的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;
Run Code Online (Sandbox Code Playgroud)

如果我将其复制并粘贴到psql(PostgreSQL的shell)中,那么它会毫无问题地执行.

如果我像这样编写一段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)
Run Code Online (Sandbox Code Playgroud)

似乎执行(它不会给我一个错误),但当我查看数据库时,函数不存在.

当我尝试通过将它放入app/sql/model.sql文件来执行Django中的代码时,我在syncdb期间收到以下错误:

IndexError: tuple index out of range
Run Code Online (Sandbox Code Playgroud)

当我尝试编写自己的执行sql的manage.py命令时,我得到了同样的错误.

这里发生了什么?非常感谢任何可以阐明这一点的人:)在Python和Django方面,我仍然是一个新手,所以我可能忽略了一些明显的东西.

int*_*tgr 30

默认情况下,psycopg2使用%符号标识参数占位符(通常%s在字符串中有).

所以,如果你使用cursor.execute('... %s, %s ...', (arg1, arg2))那么那些%s分别变成了arg1和arg2的值.

但是,因为你调用:cursor.execute(sql_function_above),没有额外的参数,并且你的SQL包含%符号,库试图找到传递给函数的第二个参数 - 它超出范围,因此是一个IndexError.

解决方案:而不是使用%,写入%%您的SQL变量.在将%它发送到PostgreSQL之前,它会被翻译成文字.