PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

plpgsql - използване на името на динамична таблица в оператора за деклариране

Важно е да разберете основното естество на тези пет различни вида данни/символ :

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 вместо това.

Ако искате също да върнете набор от променливи тип ред:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. regexp_matches по-добър начин да се отървете от връщането на къдрави скоби

  2. Двама собственици на една и съща база данни PostgreSQL

  3. Клаузи за грижа:Всичко за SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY и LIMIT

  4. Съобщение 28000:няма запис в pg_hba.conf за хост \xx.xxx.xxx.xxxx\, потребител \User, база данни \databasename\, SSL изключен

  5. PostgreSQL, брой редове между мин. и макс. дати