Nem szall el, csak nem veszi figyelembe a szabalyt. Nem ujdonsag, elegge kehes a min-max, mar akkor kiirtottuk karakteres hasznalatat, amikor sajat nls filet kezdtunk hasznalni es kiderultek a problemai.. Most csak kiprobaltam :-)
Jól mondják itt az okos emberek, hogy erre a VPD van kitalálva.
De esetleg így is lehet próbálkozni egyszerűbb eszközökkel: 1) Két nézetet elkészíteni (teljes és korlátozott) 2) Az eredeti tábla publikus elérését megszüntetni 3a) Privilegizált felhasználók kapnak egy saját szinonimát + select jogot a teljes nézetre 3b) Mezei felhasználók kapnak egy saját szinonimát + select jogot a korlátozott nézetre 4) Ha írni is akarnak, nem csak olvasni, akkor pedig jöhetnek az Instead of triggerek.
Az lenne a kérdésem, hogy OCI-ból (pontosabban cx_Oracle-ből, de az is OCI-t használ) lehet-e úgy tárolt eljárást hívni, hogy PL/SQL RECORD ill. PL/SQL TABLE típusú argumentumai vannak az eljárásnak, és ezeket a hívó fél tölti?
Egy (RONDA) megoldásom van rá (TYPE xx_typ IS TABLE OF VARCHAR2 INDEX BY BINARY_INTEGER - azaz tömb típust tudok átadni; "csak" szészedem a rekordot ilyen tömbökre, és egy PL/SQL blokkba ágyazom a megfelelő típusú változó feltöltését ezekből).
Amíg nem volt VPD, addig leánykori nevén FGAC volt, ami neked kellhet: Fine Grained Access Controll. Ez session-infók + jogosultság alapján bővíti az sql where-feltételét a háttérben. Így hiába 100 rekordos a tábla -> a select count(*) from tabla az általad látott mondjuk 30-at fogja visszaadni, sql*plusban is (ennek a további Oracle általi where-szűkítésnek köszönhetően). A mögöttes implikáló elgondolás az volt, annó, hogy pl.: egy nagy könyvelőcég, aki több kis cégnek könyvel, teljesen szeparáltan tudja kezelni a könyvelendő cégeket egy adatbázison belül, "single instance" elv mentén...
VPD = Virtual Private Database Ha a userek azonosíthatók a bejelentkezéskor, egy logontriggerrel a sessionre vonatkozóan tudsz infókat tárolni, amiben megadod a user üzleti szerepkörét. Ezt az infót pedig a táblára rakott policy-vel felhasználhatod. A policy hozzáteszi a megfelelő where feltételt a táblára elhangzó összes selecthez. Biztos nem ez a világ legegyszerűbb megoldása, de ha nem connection poolt használ a kliensed, akkor biztos működik. Connection pool esetén a session-ben tárolt üzleti szerepkör infót az alkalmazásnak kell váltogatnia. Talán van rá valami automatizmus Oracle AS 10g-ben, de ebben nem vagyok nagyon otthon. Ha simán a user nevéből, vagy valami értelmes, a sessionből egyébként is elérhető paraméterből eldönthető, hogy ki mit lát, elég csak a policyt használnod, nem kell a logon triggerrel szenvedned. Ha nagyon intenzíven használják a táblát, akkor okozhat teljesítményromlást, hiszen a policy fv.-t le kell futtatni, hogy kitalálja, mi legyen a where feltétel. De erre is vannak beállítások, hogy milyen esetekben tudja cacheelni ezt az infót. Ha pl. egy oracle usernév alapján eldönthető feltételről van szó, elég sessionönként egyszer kiértékelni a fv-t, a többi alkalommal egyszerűen csak hozzácsapja és kész - marad a softparse, ami nem túl vészes költség ugyebár.
Egy kis segitsegre lenne szuksegem... Egy mar mukodo rendszeren kellene ugy modositani, hogy nehany tablara rekord szintu select jogot kellene bizonyos felteteleknek megfelelo felhasznaloknak adni. Tehat lennenek az adott tablaknak olyan rekordjai, amiket csak kituntetett felhasznalok lathatnanak, vagy esetleg az adott rekordok nehany mezojet zanzasitva (termeszetesen kliens programtol fuggetlenul). Emlekszem, hogy volt valamilyen hasonlo, tamogatott adatbazis oldali megoldas, de egesz egyszeruen nem talalom a doksiban. 10gR2
Ha meghívod a progit akár sqlplusból, hibára fut és nem kezeled le sehol a kódban, amúgyis megkapod a hibaüzenetet.
Természetesen a logikai hibákat kaphatod csak el, de működés szempontjából az ORA-600 és ORA-7445 hibák, amik a server process leállásával járnak nyilván nem számítanak :)
Alapból tranzakcióban vagy. Tehát ha semmit nem csinálsz, akkor az az alapértelmezett működés, amit kértél. Arra vigyázni kell, hogy minden korábbi változás is elveszett, hiszen nem kezdtél új tranzakciót. Némi problémát okozhat, hogy az a működési mehanizmus, hogy kapsz egy hibát, ami az álltalad megadott kódban nem kezelődik, tehát valaki majd vagy lekezeli, vagy hibára fut a hívás. Ha teszel bele hibakezelést, akkor megkaphatod azt a viselkedést, amit szerintem szeretnél:
PROCEDURE xyz (n NUMBER) IS BEGIN BEGIN DELETE from ...; DELETE from ...; DELETE from ...; COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; END; END xyz;
Ha pontosan tudod, hogy milyen hiba esetén nem kellene commitálnod, de a program futhat tovább, akkor definiálnod kéne az exception-t a megfelelő hibakódhoz és azt elkapni a hibakezelésben.
Ha azt szeretnéd, hogy csak ez a 3 delete legyen tranzakcióban és a hívó DML-jeit nem szeretnéd rollbackelni vagy commitálni, akkor a defininálnod kell, hogy ez egy autonóm tranzakció a "PRAGMA AUTONOMOUS_TRANSACTION" sorral. Ehhez még heggesztettem egy kis egyedi hibakezelést is:
PROCEDURE xyz (n NUMBER) IS PRAGMA AUTONOMOUS_TRANSACTION; e_role_exists EXCEPTION; PRAGMA EXCEPTION_INIT (e_role_exists, -1921); BEGIN BEGIN DELETE from ...; DELETE from ...; DELETE from ...; COMMIT; EXCEPTION WHEN e_role_exists THEN ROLLBACK; END; END xyz;
Ezesetben csak a saját kódjára nyit egy tranzakciót és csak azt fogja rollbackelni, ráadásul csak akkor, ha ORA-1921-es hibát kap (amit deletenél nem kapsz, de ez volt a kódomban: arra definiálod, amire akarod, csak negatív legyen a szám :)) Más hibákat nem kezel le, így azok feljebb adódnak és meghal a futás a hiba kódjával.
Nem, a procedure egyáltalán nem számít a tranzakciókezelés szempontjából, a ROLLBACK vagy mindent visszacsinál, ami a legutóbbi COMMIT-óta történt, vagy azt ami a megadott SAVEPOINT óta történt...
Lehetséges megközelítések:
1. A procedure-ban nincs semmilyen tranzakciókezelés, a hívó a visszaadott értékből tudja meg, hogy sikeres volt-e, vagy sem, és ő majd COMMIT-ál vagy ROLLBACK-el saját belátása szerint.
2. A procedure-ban van COMMIT siker esetén, és ROLLBACK kudarc esetén.
3. Ugyanez, de autonóm tranzakciókezeléssel, mondjuk ha a procedure egy napló írása, amibe akkor is kell bejegyzést tenni, ha végül a művelet nem is történik meg.
4. Ha a procedure sikeres volt, akkor nincs semmi, majd a hívó COMMIT-ál, Ha valami nem sikerült, akkor a procedure elején lévő SAVEPOINT-ig ROLLBACK-el.
Legfontosabb, hogy aki hívja a procedurádat, az tudjon arról, hogy az hogyan is működik, vö: "Bakker, ebben volt egy COMMIT?!"
Köszi az eddigi segítséget, úgy néz ki, sikerült átvergődnöm a dolgon.
Az importnál készített log alapján kiderült, milyen tablespace-ek kellenek, és azt a kettőt létrehoztam TOAD-dal.
Ezután majd az lesz nagy falat (persze ha a többi normál adatbázis import sikeresen lezajlott), hogy koreai cuccok is vannak, amihez UTF-8-as karakterkészlet dukál.
Igaz, hogy ahhoz egy új Oracle instance-t kell telepíteni?