Подтвердить что ты не робот

Почему psycopg2 не выполняет какие-либо мои SQL-функции? (IndexError: индекс tuple выходит за пределы диапазона)

Я возьму простейшую из 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)

Кажется, выполняется (это не дает мне ошибку), но когда я смотрю в базу данных, функции там нет.

Когда я пытаюсь выполнить код в Django, поместив его в файл app/sql/model.sql, во время syncdb я получаю следующую ошибку:

IndexError: tuple index out of range

Когда я пытаюсь написать свою собственную команду manage.py, которая будет выполнять sql, я получаю ту же ошибку.

Что здесь происходит? Был бы очень благодарен всем, кто мог бы пролить свет на это:) Я все еще новичок, когда дело доходит до Python и Django, поэтому я, возможно, пропустил что-то очевидное.

4b9b3361

Ответ 1

По умолчанию psycopg2 идентифицирует местозаполнители аргументов, используя символ % (обычно у вас есть %s в строке).

Итак, если вы используете cursor.execute('... %s, %s ...', (arg1, arg2)), тогда те %s превращаются в значения arg1 и arg2 соответственно.

Но так как вы вызываете: cursor.execute(sql_function_above), без дополнительных аргументов, а ваш SQL включает в себя % признаки, библиотека пытается найти второй аргумент, переданный в функцию - вне диапазона, следовательно, IndexError.

Решение: Вместо использования % напишите %% в своей переменной SQL. Это преобразуется в литерал % перед отправкой в ​​PostgreSQL.

Ответ 2

Похоже, вы не совершаете транзакцию:

Попробуйте поставить:

cursor.execute("COMMIT")

После последней строки и посмотрите, работает ли это.

Вы также можете установить уровень изоляции для автозапуска, например:

connection.set_isolation_level(0)

Подробнее о том, что в этом ответе

Ответ 3

Индекс вне диапазона означает, что вы пытались получить доступ (например) к третьему элементу кортежа, который имеет только два элемента. Обратите внимание, что индексы Python начинаются с 0, поэтому двухэлементный кортеж с именем myTuple будет иметь элементы myTuple [0] и myTuple [1], но ни один элемент myTuple [2].