Sziasztok!
Nem vagyok sajna eléggé tapasztalt a témában, ezért kérem a segítségeteket. Hogyan tudom azt a rekordot kivenni az adatbázisból, amit beszúrtam, és egy szekvenciával kapott primary key-t?
Eddig odáig jutottam, hogy a "SELECT seq.* FROM all_sequences seq WHERE ..." visszaadja a LAST_NUMBERT, de mivel van egy cache-ja a dolognak, így ez a szám a cachelt értéken túli első "szabad" szám. A "SELECT * FROM foo WHERE id = (select MAX(id) FROM foo)"-val az a bajom, hogy ha időközben volt másik insert, akkor nem jó rekordot kapok vissza. Próbálkoztam az "INSERT INTO ... RETURNING id INTO x" de ez nem akarta az igazságot.
Tudom széjjelrágott csont, de bénaságomból adódóan nem találok normális megoldást egy ideje.
Előre is köszi a segítségeteket.
- 1416 megtekintés
Hozzászólások
DECLARE
xx PLS_INTEGER;
BEGIN
insert into ... values ...
returning id into xx;
dbms_output.put_line(xx);
insert into id, ... values (seq_neve.NEXTVAL, ...);
select seq_neve.CURRVAL INTO xx;
dbms_output.put_line(xx);
end;
- A hozzászóláshoz be kell jelentkezni
Én ezt egy hagyományos insert után szeretném használni, egy általános osztályt írok ugyanis, ami auto incrementes pk-val megáldott tábla rekordjait képes kezelni, így nem feltételezhetetek semilyen tárolt eljárást. Van a tábla meg mennek bele az adatok, nekem meg kell, amit utoljára beszúrtam. :(
- A hozzászóláshoz be kell jelentkezni
Ott van: seq_neve.CURRVAL
- A hozzászóláshoz be kell jelentkezni
Köszi, és ez az ellen véd, ha a beszúrás és a currval lekérdezés között egy másik kliens is beszúrt egy sort?
- A hozzászóláshoz be kell jelentkezni
Igen. Pontosabban: mindig azt adja vissza, amit az aktuális session-ben utoljára használtál.
- A hozzászóláshoz be kell jelentkezni
Köszi
- A hozzászóláshoz be kell jelentkezni
Esetleg arra nincs tipped hogyan tudom meg, hogy adott mezőhöz tartozik-e sequencia? és ha igen hogy hívják?
- A hozzászóláshoz be kell jelentkezni
A szekvenciak nincsenek oszlopokhoz (mezokhoz) rendelve. A jogosultsagi rendszer adta kereteken belul akarki hasznalhatja az altaluk szolgaltatott ertekeket tetszoleges celra.
Komplex logika eseten mindez egy oszlophoz rendelt megoldasnal lenyegesen nagyobb rugalmassagot biztosit.
A szekvenciaknak csupan egy celja van: automatikus egyedi azonositok generalasa megfelelo teljesitmeny mellett, kivant szabalyok betartasaval.
Ha nagyon reverse-engineerelos kedvedben vagy, akkor a parsolt SQL utasitasok szovegebol kihamozhato, h. mely statementek, mely szekvenciakat mely oszlopok feltoltesekor hasznaljak. V$SQL v. barmely nezet jo, amely a shared_pool-ban tarolt vegrahajtasi tervekhez tartozo szoveges SQL utasitast tartalmazza. Ez nem szep megoldas, alkalmazasfejlesztes soran ne is gondolj ra, de pl. egy rendszer megismerese soran elfogadhato tajekoztato jelleggel.
- A hozzászóláshoz be kell jelentkezni
Sejtettem, hogy ez lesz a bibi. Ezek szerint rövidke Oracles pályafutásom alatt rögtön belefutottam egy dologba, amit nem lehet Oracle-val megoldani :(. Olyan osztály akartam készíteni, aminek megmondod melyik táblával dolgozzon, és a tábla szerklezete alapján tud beszúrni, frissíteni, törölni, validálni, meg leválogatni rekordokat. Minden működik is kivéve azt, hogy beszúrás után visszaadja a metódus a beszúrt rekordot mégpedig úgy, hogy újra kiolvassa az adatbázisból. Az osztály MySQL-es verziója nagyon jól működött, és 80% levette az adatbázisban matatást a vállamról, ehelyett objektumokkal kellett csak dolgoznom. Oracle-ben ezek szerint legalább még a sequencia nevét tudnom kell ahhoz, hogy ugyanazt a funkcionalitást elérjem. Szomorú, persze tudom van értelme, meg a rugalmasság, de most épp a rugalmasságát vesztette el a dolog.
- A hozzászóláshoz be kell jelentkezni
Meg lehet oldani triggerekkel. A last_insert_id() funkcionalitáshoz
1) használod a szekvencia nevét
2) a legelső hozzászólásban látott látott "...returning id into valtozo" megoldást használod
Az se rossz, ha *egyetlen* szekvenciát használsz az egész szoftverben. Az ID-k nem lesznek olyan folyamatosak, de ez technikailag nem gond.
Upd.: ha a triggereket úgy írod meg, hogy egy globális package változóba eltárolják a legutolsó szekvencia ID-ket, akkor végül is több szekvenciát is használhatsz. Gyakorlatilag tökéletesen tudod emulálni a last_insert_id()-t.
- A hozzászóláshoz be kell jelentkezni
Hát épp az a baj, hogy általános megoldást szeretnék nem akarom tudni a seq nevét, nem akarok egy seq-et használni, stb. Annyit szeretnék, mint írtam, hogy megadom a PHP osztályomnak a tábla nevét, és $newEntity = $oszt->insert($entity) és a beszúrt rekordot adja vissza úgy, hogy kiolvassa a db-ből.
- A hozzászóláshoz be kell jelentkezni
van egy másik oracle-érdekesség is, ha már így előhoztad a tervezett felhasználást:
beszúrsz egy üres stringet, és kiolvasáskor NULL-t kapsz... :)
- A hozzászóláshoz be kell jelentkezni
Az én szememben ez inkább feature :)
- A hozzászóláshoz be kell jelentkezni
Adtam pár ötletet, ezekkel szerintem lehet boldogulni.
- A hozzászóláshoz be kell jelentkezni
akkor viszont maradnak a string műveletek,
a seq neve legyen a táblanév_seq
és így valahogy :
L_EXEC := 'select '....|| ...
EXECUTE IMMEDIATE L_EXEC USING Param1, ... ;
és/vagy
cursor_name := dbms_sql.open_cursor;
dbms_sql.parse(cursor_name, 'begin :aret := ' || fv_név || '(:param1,... dbms_sql.v7);
dbms_sql.bind_variable(cursor_name, ':aret', dinaret);
..
..
result := dbms_sql.execute(cursor_name);
dbms_sql.variable_value(cursor_name, ':l_dret', dinaret);
..
..
persze ennél az a baj, ha sokan hajtják, akkor sokat parcol az oracle.
- A hozzászóláshoz be kell jelentkezni
Attol fugg milyen kliens lib-et hasznalsz, altalaban mindben van tamogatas, a beszurt mezo id-nek lekerdeesere, pl. jdbc-ben van ilyen.
java.sql.Statement
public ResultSet getGeneratedKeys() throws SQLException;
Ja es ez szabvany:
In JDBC 3.0, the java.sql.DatabaseMetaData interface provides the following method:
public boolean supportsGetGeneratedKeys();
- A hozzászóláshoz be kell jelentkezni
PHP alatt/felett kell sajnos dolgoznom, és az oci_connect egyébként is egy nagy rakás...
- A hozzászóláshoz be kell jelentkezni