我将以最简单的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方面仍然是新手,所以我可能忽略了一些显而易见的事情。
答案 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]。