Сегодня утром немножко сломался скриптик, импортирующий в базу записи, приезжающие от партнёра. Скриптик рабочий, трудится уже много месяцев. Да и сломался он не совсем - не может добавить в таблицу некоторые отдельные записи. Остальные успешно добавляет, а эти никак.

Попытался вручную - натурально не добавляется. “Unique constraint (foo.bar) violated, пошли все нафиг” - говорит сервер. Ищу запись по ID - нет такой. Внимательно приглядываюсь к описанию violated constraint и обнаруживаю, что это про уникальность имени, а не ID. Ищу запись по такому имени - а её тоже нет. Но новая не добавляется. Чертовщина какая-то.

А разгадка оказалась проста. Можно предлагать в качестве задания на собеседовании DBA :)

Read the rest of this entry »

Пишем простейшую хранимую процедуру, которая умеет иногда генерировать исключения:

CREATE PROCEDURE tmp_proc (
  p_foo int
)
  IF p_foo = 0 THEN
    RAISE EXCEPTION -746, 0, "tmp_proc-raised exception";
  END IF
END PROCEDURE;

Вызываем её из перла посредством DBD::Informix:
“EXECUTE PROCEDURE tmp_proc (p_foo = ?)”, prepare, execute..

Как ожидалось, получаем

DBI::err = '-746', DBI::errstr='SQL: -746: tmp_proc-raised exception'

Преобразуем процедуру в функцию:

CREATE PROCEDURE tmp_func (
  p_foo int
)
RETURNING int;
  DEFINE foo int;
  IF p_foo = 0 THEN
    RAISE EXCEPTION -746, 0, "tmp_func-raised exception";
  END IF
  LET foo = p_foo+1;
RETURN foo;
END PROCEDURE;

“EXECUTE PROCEDURE tmp_func (p_foo = ?)”, prepare, execute..

И фиг там. execute успешно отрабатывает, возвращает 0E0, DBI::err и DBI::errstr совершенно undefined, всё прекрасно, никаких ошибок.

А вот если потом вызвать fetchrow_array(), то только тогда

DBI::err = '-746', DBI::errstr='SQL: -746: tmp_func-raised exception'.

Что совсем плохо, если какой-нибудь fetch() совсем не вызывать, то функция, похоже, совсем не запускается. Либо результаты её работы откатываются. Потому что изначально я на это наткнулся на функции, которая проверяет данные, добавляет строку в таблицу и возвращает ID от добавленной строки. Вот если этот ID потом не считать с помощью fetch, то данные в таблицу вообще не попадают.

Я даже не понимаю, куда тут копать..

Есть табличка tbl. В ней есть записи нескольких типов, различаются по значению поля type. Кроме того, есть поле disporder (числовое, определяет, в каком порядке записи должны показываться пользователю) и поле prio (приоритет, может быть ‘Y’ или ‘N’). Для записей типа 1 prio может быть равен ‘Y’ максимум у одной записи в таблице, а может вообще у всех быть ‘N’.

Задача: одним запросом вывести из таблицы поле title (и только его) для всех записей типа 2, а также для первых трёх (в порядке prio+disporder) записей типа 1, причём выборка должна быть отсортирована в целом по disporder, но если в выборке встречается запись типа 1, у которой prio=’Y', то она должна оказаться на первом месте.

Пользоваться можно вашим любимым диалектом SQL, а в моём для полного счастья не допускается FIRST и ORDER BY в SELECT’ах, объединенных в UNION. UNION, понятное дело, можно сортировать только целиком и только по полям, присутствующим во всех входящих в него SELECT’ах.

Запрос
SELECT "http://domain.tld/dir/" || tbl.image FROM tbl
не работает: Found a quote for which there is no matching quote.
Если кавычки заменить на одиночные, то работает. И если убрать один слэш после http:, то тоже работает, только результат получается не тот, который нужен. (Это Informix, если что).

Не работает из Aqua Data Studio. Есть такой графический клиент на джаве, поддерживающий кучу разных СУБД. А из консольного клиента прекрасно работает во всех вариантах.

Вопрос: кто виноват (Aqua, jdbc, …), и как им удалось этого добиться?