sql >> Databáze >  >> RDS >> PostgreSQL

IS NOT NULL test pro záznam nevrací hodnotu TRUE, když je nastavena proměnná

Vidím dva možné důvody, proč ...

Žádné z těchto zvýšení se neobjeví v mém protokolu zpráv

Nepřihlášeno

Nejprve NOTICE se normálně nezapisuje do protokolu databáze s výchozím nastavením. Zde cituji manuál:

log_min_messages (enum )

Řídí, které úrovně zpráv se zapisují do protokolu serveru. Platné hodnoty jsou DEBUG5 , DEBUG4 , DEBUG3 , DEBUG2 , DEBUG1 , INFO , NOTICE , NOTICE , ERROR , LOG , FATAL a PANIC . (...)
Výchozí nastavení je VAROVÁNÍ . Všimněte si, že LOG má zde jiné hodnocení než v client_min_messages .

Odvážný důraz můj. Všimněte si také odlišné výchozí hodnoty (NOTICE ) pro client_min_messages (předchozí položka v návodu).

Neplatný test

Za druhé zvažte, jak se vyhodnocuje výraz řádku. Testovací row_variable IS NULL vrátí TRUE if (a pouze pokud) každý jednotlivý prvek je NULL . V následujícím příkladu:

SELECT (1, NULL) IS NULL AS a     -- FALSE
      ,(1, NULL) IS NOT NULL AS b -- also FALSE

Oba výrazy vrací FALSE . Jinými slovy, proměnná řádku (nebo záznamu) (1, NULL) není ani NULL , ani to není NOT NULL . Oba vaše testy proto selžou.

-> SQLfiddle s dalšími podrobnostmi.

Další podrobnosti, vysvětlení, odkazy a možná aplikace pro toto chování v CHECK omezení v této související odpovědi:
NOT NULL omezení přes sadu sloupců

Můžete dokonce přiřadit proměnnou záznamu s hodnotou NULL (rec := NULL ), což má za následek, že každý prvek je NULL - pokud je typ dobře známý typ řádku. Jinak máme co do činění s anonymním záznamem a struktura je nedefinovaná a pro začátek nemáte přístup k prvkům. Ale to není případ rowtype jako ve vašem příkladu (který je vždy dobře známý).

Řešení:FOUND

Jaký je správný způsob, jak otestovat, zda jste obdrželi řádek z SELECT * INTO ?

Musíte vzít v úvahu, že řádek může být NULL, i když byl přiřazen. Dotaz mohl velmi dobře vrátit spoustu hodnot NULL (pokud definice tabulky ve vašem dotazu umožňuje hodnoty NULL). Takový test by byl nespolehlivý z hlediska návrhu.

Existuje jednoduchý a bezpečný přístup. Použijte GET DIAGNOSTICS ... nebo (pokud je to možné) speciální proměnná FOUND :

SELECT * FROM my_table WHERE owner_id = 6 INTO my_var;

IF NOT FOUND THEN
   RAISE NOTICE 'Query did not return a row!';
END IF;

Podrobnosti v návodu.




  1. Převést „datetime2“ na „datetimeoffset“ v SQL Server (příklady T-SQL)

  2. Oracle:sekvence MySequence.currval ještě není v této relaci definována

  3. ScaleGrid DBaaS v užším výběru pro Cloud Excellence Awards 2018

  4. MySQL – ORDER BY hodnot v IN()