Máte několik různých tabulek s přesně stejnými názvy sloupců a datovými typy? Voní jako riskantní design.
Každopádně nemůžeme takto používat proměnné jako databázové objekty v přímém SQL. Musíme použít dynamické SQL.
PROCEDURE P_CUSTOMER_UPDATE
(
pADSLTable IN USER_TABLES.table_name%type,
pAccountname IN NVARCHAR2,
pStatus IN NUMBER,
pNote IN NVARCHAR2,
pEmail IN NVARCHAR2,
pMobi IN NVARCHAR2,
pServiceTypeID IN NUMBER,
pDate IN DATE
)
IS
BEGIN
execute immediate
'UPDATE '||pADSLTable
||' SET STATUS = :1, NOTE = :2, EMAIL = :3, MOBI = :4, SERVICETYPE_ID = :5, ACTIVATION_DATE = :6'
||' WHERE ACCOUNT_NAME = :7'
using pStatus, pNote, pEmail, pMobi, pServiceTypeID, pDate, pAccountname;
END;
Jedním z důvodů, proč se vyhnout použití dynamického SQL, je jeho náchylnost ke zneužití. Zlomyslní lidé se mohou pomocí parametrů pokusit obejít naše zabezpečení. Tomu se říká SQL injection. Myslím, že lidé nadhodnocují význam SQL injection. Není to automaticky hrozba. Pokud je například procedura soukromou procedurou v balíčku (tj. není deklarována ve specifikaci), je nepravděpodobné, že ji někdo unese.
Ale je rozumné přijmout opatření. DBMS_ASSERT je balíček představený v Oracle 10g k zachycení pokusů o útoky SQL injection. V tomto případě by stálo za to jej použít k ověření předávaného názvu tabulky
....
'UPDATE '|| DBMS_ASSERT.simple_sql_name(pADSLTable)
....
To by zabránilo komukoli předat 'pay_table set salary = salary * 10 where id = 1234 --'
jako parametr názvu tabulky.
Dalším důvodem, proč se vyhnout dynamickému SQL, je to, že je obtížnější jej správně nastavit a obtížněji ladit. Syntaxe skutečného příkazu se kontroluje pouze za běhu. Je dobré mít kompletní sadu testů jednotek, které ověřují všechny předané vstupy, aby bylo zajištěno, že procedura nevyvolá výjimku ze syntaxe.
Konečně, takové dynamické SQL se nezobrazuje v pohledech, jako je ALL_DEPENDENCIES. To ztěžuje provádění analýzy dopadu a nalezení všech programů, které používají danou tabulku nebo sloupec.