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

时间:2009-11-14 16:55:29

标签: 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;

如果我将其复制并粘贴到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)

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

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

IndexError: tuple index out of range

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

这里发生了什么?非常感谢任何能够对此有所了解的人:)我在Python和Django方面仍然是新手,所以我可能忽略了一些显而易见的事情。

3 个答案:

答案 0 :(得分:29)

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

因此,如果您使用cursor.execute('... %s, %s ...', (arg1, arg2)),那么%s将分别转为arg1和arg2的值。​​

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

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

答案 1 :(得分:3)

看起来你没有提交交易:

尝试推杆:

cursor.execute("COMMIT")

在最后一行之后,看看是否有效。

您还可以将隔离级别设置为自动提交,如:

connection.set_isolation_level(0)

有关此answer

的更多信息

答案 2 :(得分:1)

索引超出范围意味着您已尝试访问(例如)仅包含两个元素的元组的第三个元素。请注意,Python的索引从0开始,因此名为myTuple的双元素元组将包含元素myTuple [0]和myTuple [1],但没有元素myTuple [2]。