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 的 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 时,我仍然是新手,所以我可能忽略了一些明显的事情。

4

3 回答 3

31

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

所以,如果你使用它们,cursor.execute('... %s, %s ...', (arg1, arg2))它们%s会分别变成 arg1 和 arg2 的值。

但是由于您调用 : cursor.execute(sql_function_above),没有额外的参数,并且您的 SQL 包含%符号库正在尝试查找传递给函数的第二个参数——超出范围,因此出现 IndexError。

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

于 2009-11-14T21:54:17.840 回答
3

看起来你没有提交交易:

尝试放置:

cursor.execute("提交")

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

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

connection.set_isolation_level(0)

有关此答案的更多信息

于 2009-11-14T17:18:13.747 回答
1

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

于 2009-11-14T17:02:12.283 回答