prosím pomozte...opravdu to potřebuji...
Ne, nechceš. Nejsem si jistý, že budete věnovat pozornost; a není důvod, proč byste měli :-) ale:
Neukládejte věk do databáze. Určitě se občas zmýlíte. Věk se u každého člověka mění každý rok, u některých se však mění každý den. To zase znamená, že potřebujete každý den spouštět dávkovou úlohu a aktualizovat věk. Pokud to selže nebo není extrémně přísné a dostanete se dvakrát, máte potíže.
Měli byste vždy vypočítat věk, kdy to potřebujete. Je to poměrně jednoduchý dotaz a z dlouhodobého hlediska vám ušetří spoustu bolesti.
select floor(months_between(sysdate,<dob>)/12) from dual
Nastavil jsem malou SQL Fiddle, abych ji demonstroval
Nyní, abych skutečně odpověděl na vaši otázku
tento postup funguje dobře, ale pouze pro jeden řádek,,,ale pro všechny řádky potřebují spouštěč, ale pokud jej zavolám ze spouštěče, dojde k chybě...
Nezmiňujete chybu, udělejte to prosím v budoucnu, protože je to velmi užitečné, ale mám podezření, že dostáváte
ORA-04091:tabulka string.string mutuje, spouštěč/funkce to nemusí vidět
Důvodem je, že váš postup dotazuje tabulku, která je aktualizována. Oracle to neumožňuje, aby zachoval konzistentní zobrazení dat pro čtení. Způsob, jak se tomu vyhnout, je nedotazovat se na tabulku, což nemusíte dělat. Změňte svůj postup na funkci, která vrací správný výsledek s datem narození:
function get_age (pDOB date) return number is
/* Return the the number of full years between
the date given and sysdate.
*/
begin
return floor(months_between(sysdate,pDOB)/12);
end;
Ještě jednou si všimněte, že používám months_between()
fungovat, protože ne všechny roky mají 365 dní.
Ve vašem spouštěči pak přiřadíte hodnotu přímo sloupci.
CREATE OR REPLACE TRIGGER agec before INSERT OR UPDATE ON dates
FOR EACH ROW
BEGIN
:new.age := get_age(:new.dob);
END;
:new.<column>
syntaxe je odkaz na <column>
který se aktualizuje. V tomto případě :new.age
je skutečná hodnota, která bude vložena do tabulky.
To znamená, že vaše tabulka bude automaticky aktualizována, což je bod spouštěče DML.
Jak vidíte, tato funkce nemá vůbec žádný smysl; váš spouštěč se může stát
CREATE OR REPLACE TRIGGER agec before INSERT OR UPDATE ON dates
FOR EACH ROW
BEGIN
:new.age := floor(months_between(sysdate,:new,DOB)/12);
END;
Nicméně, pokud budete tuto funkci používat jinde v databázi, ponechte ji oddělenou. Je dobrým zvykem ponechat kód, který se používá na více místech ve funkci, jako je tato, aby byl vždy používán stejným způsobem. Zajišťuje také, že kdykoli někdo spočítá věk, udělá to správně.
Trochu stranou, jste si jistý, že chcete umožnit lidem, aby byli starší 9999 let? Nebo 0,000000000001998 (důkaz)? Numerická přesnost je založena na počtu významných číslice; toto (podle Oracle) je nenulové pouze čísla. Můžete se tím snadno nechat nachytat. Smyslem databáze je omezit možné vstupní hodnoty pouze na ty, které jsou platné. Vážně bych zvážil deklarování sloupce věku jako number(3,0)
abyste zajistili, že budou zahrnuty pouze "možné" hodnoty.