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

Как да използвам променливи настройки в тригерни функции?

Обработка на всички възможни случаи за персонализирана опция правилно:

  1. опцията все още не е зададена

    Всички препратки към него водят до изключение , включително current_setting() освен ако не е извикан с втория параметър missing_ok . Ръководството:

  2. опция, зададена на валиден литерал на цяло число

  3. опция, зададена на невалиден цялочислен литерал

  4. нулиране на опция (което се записва до специален случай на 3. )

    Например, ако зададете персонализирана опция с SET LOCAL или set_config('myvars.user_id3', '55', true) , стойността на опцията се нулира в края на транзакцията. Все още съществува , може да бъде препратен, но сега връща празен низ ('' ) - което не може да бъде преобразувано в integer .

Като оставим настрана очевидните грешки във вашата демонстрация, трябва да се подготвите за всичките 4 случая. И така:

CREATE OR REPLACE FUNCTION add_transition1()
  RETURNS trigger AS
$func$
DECLARE
   _user_id text := current_setting('myvars.user_id', true);  -- see 1.
BEGIN
   IF _user_id ~ '^\d+$' THEN  -- one or more digits?

      INSERT INTO transitions1 (user_id, house_id)
      VALUES (_user_id::int, NEW.id);  -- valid int, cast is safe

   ELSE

      INSERT INTO transitions1 (user_id, house_id)
      VALUES (NULL, NEW.id);           -- use NULL instead

      RAISE WARNING 'Invalid user_id % for house_id % was reset to NULL!'
                  , quote_literal(_user_id), NEW.id;  -- optional
   END IF;

   RETURN NULL;  -- OK for AFTER trigger
END
$func$  LANGUAGE plpgsql;

db<>fiddle тук

Бележки:

  • Избягвайте имена на променливи, които съответстват на имена на колони. Много податливи на грешки. Една популярна конвенция за именуване е имената на променливите да се добавят с долна черта:_user_id .

  • Присвояване по време на деклариране, за да запазите едно присвояване. Обърнете внимание на типа данни text . Ще кастираме по-късно, след като сортираме невалидните въведени данни.

  • Избягвайте повдигане/прихващане на изключение, ако е възможно . Ръководството:

  • Тествайте за валидни низове с цели числа. Този прост регулярен израз позволява само цифри (без водещ знак, без бяло пространство):_user_id ~ '^\d+$' . Нулирам до NULL за всеки невалиден вход. Адаптирайте се към вашите нужди.

  • Добавих незадължително WARNING за ваше удобство при отстраняване на грешки.

  • Случаи 3. и 4. възникват само защото персонализираните опции са низови литерали (тип text ), валидните типове данни не могат да бъдат наложени автоматично.

Свързани:

Всичко това настрана, може да има по-елегантни решения за това, което се опитвате да правите без персонализирани опции, в зависимост от вашите точни изисквания. Може би това:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как работи IsFinite() в PostgreSQL

  2. Преобразуване на Oracle SQL Select в PostgreSQL select

  3. Postgres:Защо производителността е толкова лоша на подселекти с Offset/Limit

  4. По-стабилни съпоставяния с поддръжка на ICU в PostgreSQL 10

  5. Създайте голямо цяло число от големия край на uuid в PostgreSQL