PostgreSQL" IF " синтаксическая ошибка
Я новичок в PostgreSQL, и у меня уже есть первая проблема..
Я написал код, чтобы понять, как работают транзакции, следуя пошаговому руководству.
чтобы сделать его коротким, Я создал 2 таблицы, пользователь и движения: в первом из них есть столбцы имя, электронная почта и кредит, во втором-Столбцы от, до, импорт.
Итак, я пытался так:
BEGIN;
INSERT INTO movements (from, to, import) VALUES ('mary', 'steve', 600);
UPDATE users SET credit = credit - 600 WHERE name = 'mary';
UPDATE users SET credit = credit + 600 WHERE name = 'steve';
--here comes the problem!
IF (SELECT credit FROM users WHERE name = 'mary') < 0 THEN
ROLLBACK;
END IF
COMMIT;
Я всегда получаю ошибку:
ошибка: синтаксическая ошибка при или около "IF"
где я ошибаюсь?
P. S.: Не сосредоточиться на примере функциональности, это просто испытание для меня, чтобы понять сделок.. а теперь пункт IF...
5 ответов
Как уже говорит Йоханнес: вы смешиваете обычный SQL с PL / pgSQL, языком хранимых процедур. Ссылка, которую предоставляет Johannes, должна объяснить вам концепцию хранимых процедур.
Я так понимаю, вы делаете это как сценарий? Выполнение одного оператора за другим? Боюсь, вы можете делать только то, что хотите, внутри хранимой процедуры или функции, как вы ее называете. Это связано с тем, что при выполнении операторов таким образом каждый оператор стоит на своем собственный, не имеющий никакого отношения или информации относительно других заявлений.
кроме того, вы можете посмотреть на следующую ссылку для получения дополнительной информации о том, как использовать IF ... ЗАТЕМ... ЕЩЕ... END IF; conditionals внутри plpgsql:ссылке.
EDIT:
Я не знаю, разрешен ли откат в этот момент (потому что каждая хранимая процедура уже находится в своей собственной транзакции), но вы должны быть в состоянии понять это для себя, используя обширная документация @ http://www.postgresql.org. Вот пример функции с вашим кодом, также демонстрирующий другой синтаксис:
CREATE OR REPLACE FUNCTION public.test()
RETURNS integer AS
$$
DECLARE
tempvar integer;
BEGIN
tempvar := 1;
INSERT INTO movements (from, to, import) VALUES ('mary', 'steve', 600);
UPDATE users SET credit = credit - 600 WHERE name = 'mary';
UPDATE users SET credit = credit + 600 WHERE name = 'steve';
--here comes the problem!
IF (SELECT credit FROM users WHERE name = 'mary') < 0 THEN
ROLLBACK;
END IF;
RETURN tempvar;
END
$$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;
однако, если вы действительно идете по этому пути, я рекомендую использовать менеджер БД GUI. Все это легче усвоить.
вы, кажется, используете plain SQL
но IF
оператор является частью PL/pgSQL
процедурный язык, который является частью программы.
вы можете попробовать изменить часть IF, из:
IF (SELECT credit FROM users WHERE name = 'mary') < 0 THEN
ROLLBACK;
END IF
to
SELECT SUM(credit) INTO v_credit FROM users WHERE name = 'mary';
IF (v_credit) < 0 THEN
ROLLBACK;
END IF
предполагая, что v_credit-это переменная, определенная ранее. IMHO, Postgre предполагает, что запрос SELECT возвращает более одного результата, хотя вы уверены, что он уникален. Поэтому я думаю, что вы можете попытаться сначала назначить значение переменной.
Если вы хотите избежать, если вы можете переписать свой код как:
BEGIN;
INSERT INTO movements (from, to, import)
SELECT 'mary', 'steve', CASE credit < 600 WHEN TRUE THEN 0 ELSE 600 END;
UPDATE users SET credit = credit - CASE credit < 600 WHEN TRUE THEN 0 ELSE 600 END
WHERE name = 'mary';
UPDATE users u SET u.credit = u.credit + CASE v.credit < 600 WHEN TRUE THEN 0 ELSE 600 END
FROM users v
WHERE u.name = 'steve' and v.name = 'mary'
COMMIT;
Да, это глупо :) .
подобно Microsoft SQL и T/SQL, вы должны иметь возможность смешивать обычный SQL с PL / pgSQL, если они находятся в правильной последовательности. Вот пример, где последовательность имеет значение в смешанном SQL / PL, хранящемся proc:
вы не можете обернуть условные операторы внутри курсора-вы должны поставить курсор внутри условного оператора. Если вы сделаете последовательность наоборот, вы получите ту же ошибку, что и раньше, ' ERROR: syntax error at или near "Если":
CREATE OR REPLACE FUNCTION getSubsystemFaultListCount(_bunoid integer, _subsystem text, _starttime timestamp without time zone, _stoptime timestamp without time zone)
RETURNS refcursor AS
$BODY$
DECLARE mycurs refcursor;
BEGIN
IF _subsystem = 'ALL' THEN
OPEN mycurs FOR
SELECT count(*), fs_fault.faultcode, fs_fault.downloadtime
FROM fs_fault
WHERE fs_fault.bunoid = _bunoid
AND fs_fault.statusid IN(2, 4)
AND fs_fault.downloadtime BETWEEN _starttime AND _stoptime
GROUP BY fs_fault.faultcode, fs_fault.downloadtime;
RETURN mycurs;
ELSE
OPEN mycurs FOR
SELECT count(*), fs_fault.faultcode, fs_fault.downloadtime
FROM fs_fault
WHERE fs_fault.bunoid = _bunoid
AND fs_fault.subsystemid
IN(SELECT id FROM fs_subsystem WHERE type = _subsystem)
AND fs_fault.statusid IN(2, 4)
AND fs_fault.downloadtime BETWEEN _starttime AND _stoptime
GROUP BY fs_fault.faultcode, fs_fault.downloadtime;
RETURN mycurs;
END IF;
END;
$BODY$
Я новичок в PostGresSQL; эта функция является просто примером.