Прежде всего, вы не хотите использовать тип данных char
. Это синоним character(1)
и совершенно неправильно для передачи текста «пароль». Любая строка будет усечена до первого символа. Согласно документации:
Обозначения varchar(n)
и char(n)
являются псевдонимами для character
varying(n)
и character(n)
соответственно. character
без спецификатора длины эквивалентно character(1)
.
Далее, что не так с функцией, возвращающей TRUE
или NULL
?
Если вам действительно нужно вернуть TRUE
/FALSE
, ваша идея с использованием CTE, изменяющий данные, работает. Однако код вводит в заблуждение. Вы делаете вид, что TRUE
в финальном SELECT имеет значение, но это не так:
CREATE FUNCTION password_set(bigint, text)
RETURNS boolean AS
$func$
WITH u AS (UPDATE users SET password = $2 WHERE id = $1 RETURNING 1)
SELECT EXISTS (SELECT * FROM u)
$func$ LANGUAGE sql;
EXISTS
учитывает, только если строка вернулся. Не имеет значения, пишете ли вы NULL
, или FALSE
, или TRUE
, или *
, или 'foo'
, или что-то еще. Функция, возвращающая TRUE
, только говорит нам, что UPDATE
вернула одну или несколько строк.
Альтернативой может быть функция PL/pgSQL, использующая специальная переменная FOUND
:
CREATE OR REPLACE FUNCTION password_set(bigint, text)
RETURNS boolean AS
$func$
BEGIN
UPDATE users SET password = $2 WHERE id = $1;
IF FOUND THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END
$func$ LANGUAGE plpgsql;
Чуть быстрее и, наверное, понятнее. Или, как прокомментировал @pozs, поскольку мы возвращаемся boolean
в любом случае в данном случае просто:
RETURN FOUND;
person
Erwin Brandstetter
schedule
15.04.2014
id
УНИКАЛЬНЫМ или может быть несколько затронутых строк? Кроме того, ваша версия Postgres? - person Erwin Brandstetter   schedule 15.04.2014