Важно е да разберете основното естество на тези пет различни вида данни/символ :
1. 'my_tbl'
Литерал на низ от unknown
вида . Когато се използва в SQL (вграден в plpgsql код или не), той се принуждава към тип, извлечен от контекста . Ако типът не може да бъде определен, може да се наложи изрично преобразуване. Като:'my_tbl'::text
.
2. 'my_tbl'::text
Същият литерал на низ се прехвърля към тип text
. Може да съдържа името на таблица, но всъщност е просто текст.
3. 'my_tbl'::regclass
идентификатор на обект (OID)
за регистриран клас . Той се показва и може да бъде въведен като низ, представляващ валидно име на обект ('my_tbl'
). Резултатът е автоматично квалифициран като схема ('my_schema.my_tbl'
) и/или в двойни кавички ('"mY_TbL"'
), ако би било двусмислено или незаконно по друг начин. Може да бъде обикновена маса , последователност , преглед , материализиран изглед , съставен тип и т.н. Подробности в този свързан отговор:
4. my_tbl_var my_tbl
(съкратено от my_tbl_var my_tbl%ROWTYPE
)
В DECLARE
раздел на plpgsql кодов блок, който е декларация на променлива с добре познат тип ред
(известен още като композитен тип). Типът трябва да бъде регистриран в системната таблица pg_class
(същото като с regclass
променлива). Това не е OID на реферирания обект, а действителният му тип ред. my_tbl_var
и my_tbl
и двете са идентификатори тук и не може да се параметризира. Можете също да прехвърляте всеки ред или запис директно:(123, 'foo')::my_tbl
5. my_tbl_var record
В DECLARE
раздел на plpgsql кодов блок, който е декларацията на анонимен запис
. По принцип контейнер за все още неизвестен тип ред / с все още недефинирана структура. Може да се използва в повечето от местата, където може да се използва тип ред. Но не можете да получите достъп до полета от него, преди да бъде присвоена променливата за запис.
Объркахте 1. , 3. и 4. и го реши с помощта на 5. вместо това.
Но има още неща, които се объркват тук:
-
Избирате цяла таблица, но променлива за ред (запис) може да съдържа само един ред наведнъж. Така че само първият се присвоява и връща. Въпреки че няма
ORDER BY
клауза, резултатът е произволен и може да се промени по всяко време. Зъл капан. -
Тъй като сега използвате
record
тип, трябва да се уверите, че е присвоен, преди да можете да изпълнявате тестове на неговите полета, или ще получите изключения за празни таблици. Във вашия случай проверкатаrecord_var IS NULL
върши почти същата работа. Но има ъглов случай за редове с NULL във всички полета:тогаваrecord_var IS NULL
оценява като вярно. Още по-трудно за тестаIS NOT NULL
. Подробности тук:Добавих демонстрация към SQL fiddle по-долу.
-
Функцията връща единичен скалар (
boolean
) стойност. Използвайте:RETURN false;
Вместо:
RETURN QUERY SELECT false;
Функция
CREATE FUNCTION check_valid(_tbl regclass)
RETURNS bool AS
$func$
DECLARE
r record;
_row_ct int;
BEGIN
EXECUTE '
SELECT is_valid, hit_count, hit_limit
FROM ' || _tbl || '
ORDER <whatever>
LIMIT 1' -- replace <whatever> with your sort criteria
INTO r; -- only needed columns
GET DIAGNOSTICS _row_ct = ROW_COUNT;
IF _row_ct = 0 THEN -- necessary, because r may not be assigned
RETURN false;
ELSIF NOT r.is_valid OR r.hit_count > r.hit_limit THEN
RETURN false;
END IF;
RETURN true;
END
$func$ LANGUAGE plpgsql;
SQL Fiddle (с два варианта на функцията и демонстрация за ред IS NULL).
Основни точки
-
Използвайте
GET DIAGNOSTICS
за да разберете дали са намерени редове в динамичен оператор сEXECUTE
. -
IF
изразът може да бъде опростен. -
Параметърът е от тип
regclass
, а не просто име на таблица. Не бих използвал подвеждащото име "tablename" за този параметър. Това само допринася за първоначалното ви объркване. Наричайки го_tbl
вместо това.
Ако искате също да върнете набор от променливи тип ред: