sql >> Databáze >  >> RDS >> Oracle

Oracle – Problém při vytváření spouštěče, který aktualizuje jinou tabulku

Několik problémů v žádném konkrétním pořadí.

Nejprve v těle spouštěče na úrovni řádku musíte použít :new a :old odkazovat na nové a staré záznamy. Úvodní dvojtečka je nezbytná. Takže vaše WHERE klauzule by musela být

WHERE PROJECTID = :new.PROJECTID

Za druhé, pokud používáte CREATE TRIGGER v SQL*Plus můžete získat seznam chyb a varování pomocí SHOW ERRORS příkaz, tj.

SQL> show errors

Můžete také zadat dotaz na DBA_ERRORS tabulka (nebo ALL_ERRORS nebo USER_ERRORS v závislosti na vaší úrovni oprávnění), ale to není něco, k čemu byste se normálně museli uchýlit.

Za třetí, za předpokladu, že budou opraveny syntaktické chyby, dostanete mutující chyba tabulky pokud použijete tuto logiku. Spouštěč na úrovni řádku v tabulce A (TPM_TRAININGPLAN v tomto případě) nelze dotazovat tabulku A, protože tabulka může být v nekonzistentním stavu. Jak ukazuje Tim ve svém článku, můžete to obejít tak, že vytvoříte balíček s kolekcí, inicializujete tuto kolekci ve spouštěči příkazu before, naplníte data v kolekci ve spouštěči na úrovni řádků a poté zpracujete upravené řádky v spouštěč po příkazu. To je však slušná míra složitosti, kterou je třeba do systému přidat, protože budete muset spravovat více různých objektů.

Obecně by bylo lepší implementovat tuto logiku jako součást jakéhokoli API, které používáte k manipulaci s TPM_TRAININGPLAN stůl. Pokud se jedná o uloženou proceduru, je mnohem smysluplnější použít logiku pro aktualizaci TPM_PROJECT v této uložené proceduře spíše než její vložení do spouštěče. Je notoricky bolestivé pokoušet se ladit aplikaci, která má spoustu logiky zabudované do triggerů, protože to vývojářům velmi ztěžuje přesně sledovat, jaké operace se provádějí. Alternativně můžete odstranit TRAININGDELIVERYSTART sloupec z TPM_PROJECT a vypočítejte minimální počáteční datum za běhu.

Za čtvrté, pokud se spouštěč spustí při vložení, aktualizaci a odstranění, nemůžete jednoduše odkazovat na :new hodnoty. :new je platný pro vložení a aktualizace, ale pokud provádíte mazání, bude mít hodnotu NULL. :old je platný pro mazání a aktualizace, ale pokud provádíte vkládání, bude mít hodnotu NULL. To znamená, že pravděpodobně potřebujete mít logiku v souladu s (odkazem na Timovo řešení balíčku)

BEGIN
  IF inserting 
  THEN
    trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'INSERT');
  ELSIF updating
  THEN
    trigger_api.tab1_row_change(p_id => :new.projectid, p_action => 'UPDATE');
  ELSIF deleting
  THEN
    trigger_api.tab1_row_change(p_id => :old.projectid, p_action => 'DELETE');
  END IF;
END;


  1. Jak převést celé číslo na desítkové v SQL Server

  2. Jak mohu vymazat duplicitní položky v tabulce archivovaných záznamů

  3. Jaký je rozdíl mezi CLOB a NCLOB?

  4. Jak používat klauzuli Where v příkazu Select v SQL Server - SQL Server / Výukový program TSQL, část 109