VB.NET helyi adatbázis telepítés nélkül
2013-03-06T11:38:33+01:00
2013-07-01T22:54:00+02:00
2022-07-23T08:46:18+02:00
  • "ON DELETE CASCADE, ON UPDATE CASCADE"

    De ez sem oldja fel a problémád, hogy a max() sebessége mindenképpen több, mint egy állandóan a memóriában levő sequence db lapon egy int64 increment.
    Másrészt a select max() és a beszúrásod között más is beszúrhat ugyanarra a max()-al kapott értékre.
    Ennek feldolgozása és a ciklusban ismétlés egy szép összetett kliens oldali feladat.
    ... és mindezt miért is?

    Az egyetlen indok egy "szigorúan, kihagyás mentesen növekvő" szám (pl. számlaszám) esetén tolerálható.
    Mutasd a teljes hozzászólást!
  • Tegyük fel létrehozok egy új rekordot 11-es egyedi azonosítóval, és ugyan erre az azonosítóval bekerül egy másik táblába is adat, melyekkel össze van kötve a 2 tábla.
    De ha az 1. táblából ezt a 11-es azonosítós rekordot törlöm és újat veszek fel, a te elved szerint az újra 11-lesz és így a 2-es táblával való összekötésnél már lesz 1 false adat.
    (Törlés meg csak az 1. táblából lesz, a miértjére nem térnék ki.)


    ON DELETE CASCADE, ON UPDATE CASCADE

    ismerős?

    az a mező, amivel a két tábla össze van kötve, akkor az vagy esődleges kulcs, vagy "idegen" kulcs, legalábbis egy értelmesen összeállított adatmodellben.

    nekem egy 52 táblás könyvelőprogram készítésekor nem akadt vele gondom (mivelhogy utálom az autoinc funkciót)

    Mutasd a teljes hozzászólást!
  • Épp ezért nagyon jó a generátor, már elmondták többen, több helyen, hogy miért. Jóval túlmutatnak a lehetőségei egy egyszerű AUTOINC implementáción. Mióta ezt használom, a többi megoldást érzem kínosnak. Hogy magamat idézzem:


    Azt kell, hogy mondjam, a FireBird megoldása messze a legjobb, amivel valaha is találkoztam, pedig volt dolgom egy-két RDBMS-sel. A generátorok segítségével tulajdonképpen tetszőleges feltételeken alapuló automatizált szerveroldali üzleti logikát lehet kialakítani. Te (azaz az üzleti logika) döntöd el, hogy mikor is kell növelni egy generátor értékét és mennyivel, nameg, hogy mire használod az értékét és hol használod azt (pl. az AUTOINC csak az egyik általános felhasználása). Bármikor beállíthatod egy konkrét értékre, lényegében azt csinálsz vele, amit akarsz. Lényegében én úgy tekintek a generátorokra, mint az adatbázisban globális hatókörrel rendelkező változókra, amelyeket bárhol fel lehet használni.
    Mutasd a teljes hozzászólást!
  • "a köv módon lépd át az autoincrement problémát....."


    Ez így ahogy írtad nem jó.

    Tegyük fel létrehozok egy új rekordot 11-es egyedi azonosítóval, és ugyan erre az azonosítóval bekerül egy másik táblába is adat, melyekkel össze van kötve a 2 tábla.
    De ha az 1. táblából ezt a 11-es azonosítós rekordot törlöm és újat veszek fel, a te elved szerint az újra 11-lesz és így a 2-es táblával való összekötésnél már lesz 1 false adat.
    (Törlés meg csak az 1. táblából lesz, a miértjére nem térnék ki.)

    Szóval ez csak úgy lenne jó, ha az összes táblában átnézném hogy mi a legmagasabb egyedi azonosító, az viszont, mivel jelen esetben közel 10 táblát takar, így eléggé lassítaná a folyamatot.
    Még ellenben az auto_increment a többi adatbázisban ezt gond nélkül tudja.
    Mutasd a teljes hozzászólást!
  • Hát igen, az MGA még mindig a legjobb implementációja a "Readers don't block writers, writers don't block readers" elvnek. FB igencsak ott van a témában, már az IB is szinte a kezdetek óta MGA szerkezettel működött.
    Mutasd a teljes hozzászólást!
  • "a max értékkel nem hibázhatsz."

    Nono! (ahogy a gyárigazgató elvtárs mondotta a 'Veréb is madár' alkotásban).

    1./ A létezőség ütközésre fel kell készülni és ciklusban újra beszúrni.
    Persze egy felhasználósra tervezi, de az élet már csak olyan, hogy az ember tervez...
    2./ Mivel a FB versioning technikát alkalmaz (megjegyzem őket és persze másokat követve folyamatosan léptek át ebbe a módszertanba az ora, mssql meg ilyenek, csak sokkal később - vajh miért?), a FB-ben a max() index kulcsra nem egyszerűen az index pageből kiolvasást jelenti, hanem a rekord verziókon végigszánkázva eldönti a "valós" (tranzakció kontextben érvényes) maximumot. Ez időigényesebb lehet jóval, persze inkább csak nagy tételszámoknál, intenzív írási tranzakció használattal.
    Persze egyfelhasználós rendszernél és nem hatalmas tételszámoknál ez is érdektelen. ... no de hát az az isten csak végez olykor.
    Mutasd a teljes hozzászólást!
  • a köv módon lépd át az autoincrement problémát

    csinálsz egy függvényt vb.net-ben két paraméterrel: egy táblanév, és egy mezőnév.

    a függvény kapcsolódik az adatbázishoz, és lekéri az adott tábla adott mezőjének maximumát.

    a függvény visszatérési értéke pedig a max+1 lesz.

    lekezeled az első rekord esetét, és kész.

    az igényeid alapján úgy tűnik, hogy az embedded firebird lesz a megfelelő.

    csak kompromisszumot kell kötnöd.

    "Én részemről továbbra is biztonságosabbnak érzem, ha az adatbázis automatikusan számolja az egyedi azonosítót, mintsem, hogy én határozzam meg azt."

    miért?

    a max értékkel nem hibázhatsz.


    Mutasd a teljes hozzászólást!
  • Ráadásul a triggerrel prímán emulálható az auto increment, sőt még egzaktabb, egyénibb lehet a kiosztási feltétel.

    Az insert ... returning ... pedig felettébb egzakt módja az auto increment-el kitöltött mező visszaolvasásának.

    Nem tudom (majd ellenörzöm), de volt róla szó, hogy a default-ba ne csak konstans kerülhessen.
    A 'default CURRENT_TIMESTAMP' mező meghatározás már megy is régóta, használom.

    Igérték valamelyik verzióra, hogy a defaulthoz sequence név is kerülhet, és ekkor ez egy teljes értékű, korrekt auto increment rendszert ad, járulákos trigger írása nélkül.

    Mutasd a teljes hozzászólást!
  • A Firebird generátort használ.

    A generátor úgy működik, hogy amikor lekéred a következő értéket, az mindig egyedi lesz. Utána ezt az értéket tudod használni, mint auto-increment.

    Példa:

    SELECT NEXT VALUE FOR <SequenceName> FROM RDB$DATABASE;

    Erre visszaad 1-et.

    Amikor futtatod másodszor, 2-t és így tovább. Mindig egyedi érték lesz.

    Utána a rekordodat beszúrod ezzel, mint PK.

    A könnyebb megértés érdekében próbáld ki egy GUI programmal, pl. Firebird Maestro, ott grafikus felületen hozhatod létre és próbálhatod ki, hogy hogy működik.

    Igazából bizonyos esetekben hasznosabb lehet ez a megközelítés, mint az auto-increment, hiszen így komplexebb programoknál lehetőség van előre meghatározni az ID-t, és utána azt használni mindenütt. Egy auto-incrementes megoldásnál ugye csak beszúráskor derül ki az ID.

    Más megközelítés, ugyanaz a végeredmény. Ennyi.
    Mutasd a teljes hozzászólást!
  • Én részemről továbbra is biztonságosabbnak érzem, ha az adatbázis automatikusan számolja az egyedi azonosítót, mintsem, hogy én határozzam meg azt.

    Egy rövid példát tudnál nekem írni erről, hogy hogyan oldhatom meg a Firebird-ben az auto incrementet?
    Tudom, hogy nem szeret itt senki copy-paste megoldást kínálni, de én akárhány oldalon jártam, nem igen értettem meg, hogy hogyan működik ez a dolog firebirdnél.
    Mutasd a teljes hozzászólást!
  • "De lehet én értettem félre valamit."

    Nagyon

    Én az egész adatbázishoz (nem is táblánként) egy sequence-t hozok létre, ez egy utasítás.
    Aztán mégegy, ezt induló értékre (==1) állítás.

    Ezután párban a create table és kapcsolódó indexek, foreign definíciók, constraintok stb. mellé egy create trigger, hogy a PK feltöltése (sequence inkrementálásból) megtörténjen.

    (nálam ha a PK null or <1, akkor uniq értéket kap, eddigi belső program logikákhoz illeszkedve)

    De ma már van olyan ORM-el alátámasztott kezelésem is, ahol egyenesen nem szabad a PK-nak szerver oldalon generálni értéket.
    Ha a kliens oldalon nem kapja meg (előfoglalt sequence-ből), akkor nem lehet biztonságosan összerakni egy bonyolult keresztbe-kasul hivatkozó rekord szerkezetet.
    Vagyis ha a kliensen nem lett kiosztva a PK, egyenesen az a veszélyes és algoritmust elbonyolító koncepció

    Mutasd a teljes hozzászólást!
  • Hát ha az a legnagyobb bajod, hogy a create table mellé még egy create trigger is kerül


    Még ha csak ennyi lenne, de én amiket láttam, nemcsak annyi volt, hogy a trigger szót berakom, hanem egy külön táblát kell létrehozni minden egyes auto increment-nek szánt mezőnek.

    De lehet én értettem félre valamit.
    Mutasd a teljes hozzászólást!
  • Hát ha az a legnagyobb bajod, hogy a create table mellé még egy create trigger is kerül (egyen szöveggel!, semmi "észmunka", egyszer megír, aztán copy-paste, ne adj isten for ciklusban automatán minden táblához), na ha ennyi már gond, akkor nem is javaslom neked a Firebird-öt.

    Mert hát nem "automata", hanem azt csinálja amit kérsz tőle, jól kézbentartható.
    Van akinek ez gond, én szeretem.

    Csak egy példa, ahol az auto increment megfektet.
    Az ORM-ek vitalapjain nagyra értékelik a sequence koncepciót, ahol lekérsz akár több száz uniq id-t előre, aztán nincs gondod, hogy a beszúrt rekord auto ID-jét visszaolvasd.
    Radikális hatékonyság javulásról számoltak be master-detail szerkezetek beszúrásánál.

    Ne a "koncepciódhoz" ragaszkodj. Lehet hogy más módszertan/pattern is célhoz vezet, ne adj isten néha még hatékonyabb is


    Mutasd a teljes hozzászólást!
  • Nos ismét előjönnék valami hasonlóval, mint amivel a témát nyitottam.
    (Remélem ezért senki nem haragszik meg rám.)


    Olyan embedded adatbázist keresek amely a következő kritériumoknak megfelel:

    -- Ingyenes
    -- VB.NET kompatibilis
    -- Van saját adatbázis fájlja melyet a VB program tud használni különböző szerverek feltelepítése nélkül. (pl: dbf, mdb, sdf, s3db..)
    -- Támogatja az ékezetes betűket különféle kiegészítők nélkül mint pl ICU
    -- Emellett az ékezetekkel nincs probléma sorba rendezésnél és UPPER, LOWER függvénynél. (pl: SQLite itt igencsak elvérzik)
    -- Támogatja a GROUP_CONCAT függvényt vagy bármi hasonlót, pl list().
    -- Támogatja az "autoincrement integer" funkciót különböző kiegészítő scriptek és eljárások írása nélkül is (nem úgy mint a firebird)
    -- Nem kell telepíteni, elég pár DLL fájlt a programba implikálni.

    Ha bárki tud a fenti kritériumoknak megfelelő adatbázist ajánlani, azt nagyon szépen megköszönném.

    Az eddigiek közül az SQLite volt ami a legjobban megfelelt, az szinte mindent tud ami kell, csak sajnos az ékezetekkel nem boldogul úgy ahogy kellene.


    Amiket eddig próbáltam, és nem feleltek meg: (zárójelben a miért)
    ACCESS (fizetős, nincs group_concat-ra megoldás, ami VB-ből meghívható)
    Embedded Firebird (auto increment nincs alapból)
    Embedded MYSQL (kell neki szerver, nincs önálló sql fájlja)
    SQL Server Compact Edition (nincs group_concat megoldás)
    SQLite (ékezetes karakter problémák, UPPER, LOWER, SORTING)


    És hogy mire akarom használni az adatbázist?
    Íme, egy konkrét példa, amire jelen pillanatban kellene:

    Film adatbázis.
    1. tábla(4): Angol, magyar cím, releasedate és egy egyedi azonosító.
    2. tábla(2): stílusnevek, egyedi azonosító
    3. tábla(2): stílusazonosító, filmazonosító
    4. tábla(2): kiadó, filmazonosító

    És ezekből szeretnék egy olyan eredményt kapni amelyet nem VB-ben számolgatok meg alakítgatok, hanem már eleve így kapom:
    AngolCím | MagyarCím | releasedate | releaser1, releaser2 | stílus1, stílus2, stílus 3

    Tehát az egyértelműség kedvéért (bocs a kamu adatokért):
    SAW | Fűrész | 2006 | LionsGate, DreamWorks, WarnerBross | Krimi, Horror, Misztikus
    Mutasd a teljes hozzászólást!
  • Valóban így van, de akárhogy is nézzük, a hálózati forgalomtól eltekintve akkor is adatcsere megy végbe a beágyazott RDBMS és a kliensprogram között, ami ciklikusan végezve nagyságrendekkel többe kerül processzoridőt és memóriát tekintve, mintha csak egyetlen adatot kérne le a "szervertől". Bocsi, én itt már elvonatkoztattam, hiszen a beágyazott FB lényegében egy teljesen fullos RDBMS és már kivetítettem a fóbiáimat az általam vízionált többfelhasználós, leterhelt rendszerre is. Én általában kicsiben is nagyban gondolkodom, bár ez így lehet nem érthető.

    Mea culpa.
    Mutasd a teljes hozzászólást!
  • De még az sem kérdés, hogy C/S feladat-e.

    Kapott választ.

    Válasszon egy eszközt (pl.Firebird), aminél van server oldali program futtatás (Stored procedure ill. execute block).

    Tanulja meg (egy óránál kevesebb!!!) és uzsgyi.

    A létező eszközökkel oldja meg a feladatot.
    Mutasd a teljes hozzászólást!
  • de ha kliensoldali eszközöket is bevetünk, akkor már az egész adathalmazt át kell húzni a hálón, connection-t, reader-t létrehozni, fetch-elni, ciklusban végigmenni rajta, stringműveleteket végezni etc,etc.


    Bocsi, ez szép okfejtés, de szvsz nem erre az esetre.
    Mert ha jól sejtem, itt szó sincs hálózati forgalomról, kliens - szervver kapcsolatról, vagy tévednék?
    Mutasd a teljes hozzászólást!
  • Szerintem letisztázta az elején, hogy ne kérdezzük miért, de ez az elvárás. Egyébként osztom az elvet, én is annak vagyok a híve, hogy a komplex, adatbázisbeli adatokat és azokon végzett számításokat igénylő műveletek maradjanak a szerveroldalon, ott ahol az adatok azonnal rendelkezésre állnak. Így nem generálnak felesleges hálózati forgalmat, nameg nagyságrendekkel gyorsabb a végrehajtás is, hiszen egy arra optimalizált és a végletekig finomított motor végzi el a szükséges feladatokat. Nyilván ez itt nem egy borzasztó bonyolult és számításigényes dolog, de ha kliensoldali eszközöket is bevetünk, akkor már az egész adathalmazt át kell húzni a hálón, connection-t, reader-t létrehozni, fetch-elni, ciklusban végigmenni rajta, stringműveleteket végezni etc,etc. Ez pedig lényegében az ágyúval a verébre esete, mert miért csináljunk valamit bonyolult eszközökkel, ha könnyedén is menne?

    Meg tudom érteni.
    Mutasd a teljes hozzászólást!
  • egyébként már csak egy kérdésre nem volt válasz:

    miért kellett ezt az egészet adatbázis utasításokkak megoldani?

    miért nem volt jó megoldás a több lekérdezés egymás utáni használata?

    ezt magyarázd meg lsz.
    Mutasd a teljes hozzászólást!
  • Sok sikert!
    Mutasd a teljes hozzászólást!
  • Feladtad? Máris


    Firebird esetén Stored Procedure illetve az Execute Block komoly programozási lehetőséget ad neked Embed esetén is.

    Ha ez az eszköztár is kevés, kis munkával lehet External Procedurákat létrehozni, ami már ugye tetszőlegesen programozható. (C / Pascal, akármi ami Win32 DLL kódot hozhat létre)
    Mutasd a teljes hozzászólást!
  • Hopp ez valahogy félresikerült.
    Vigyázni kell ezzel a vágólappal.
    Valamiért nálam ha több VB van megnyitva egyszerre időnként elkezdi kutyulni a vágólapot.

    A LIST volt az ami megoldotta a problémám.
    Köszönöm mindenkinek a segítséget!
    Mutasd a teljes hozzászólást!
  • Feladtam végleg!
    Köszönöm mindenkinek a segítségét!
    Mutasd a teljes hozzászólást!
  • Ez szvsz jó, csak nála még a

    COALESCE()
    is igény, vagyis szűrni/helyettesíteni a NULL értékeket (a CASE()-hez hasonlóan).
    Mutasd a teljes hozzászólást!
  • Na, megnéztem, mit is akarsz valójában, erre FB beépített megoldást kínál:

    LIST ([ALL | DISTINCT] expression [, separator])
    Vagyis pl:


    SELECT LIST(USERNAME,';') AS USERNAMES FROM USERS WHERE ...
    Mutasd a teljes hozzászólást!
  • Ez már megint tudástár és nem társalgó téma. Ha konkrét programozási kérdésed van, akkor irány a tudástár.
    Mutasd a teljes hozzászólást!
  • fb és a mysql biztosan képes erre.

    Szeretném én is azt hinni és látni is, hogy képes rá, de eddig még csak a fényt se igazán látom az alagút végén.

    Íme a jelenlegi helyzet Firebird esetén:
    Imports FirebirdSql.Data.FirebirdClient Public Class Form1 Dim sCommand As FbBatchExecution Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load DataGridView1.Columns.Add(0, "Part") DataGridView1.Columns.Add(1, "Partn") End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'Dim sql As String = "CREATE TABLE teszt (Part int, Partn int)" Dim connection As New FbConnection("Database=e:\DBSCHOOL.FDB;User=SYSDBA;Password=masterkey;Dialect=3;ServerType=1") connection.Open() sCommand = New FbBatchExecution(connection) AddHandler sCommand.CommandExecuted, AddressOf CmdE 'sCommand.SqlStatements.Add("insert into teszt (Part, Partn) values (123, 21312);") 'sCommand.SqlStatements.Add("select * from teszt;") sCommand.SqlStatements.Add("DECLARE @UsersList varchar(1000);") sCommand.SqlStatements.Add("SELECT @UsersList = COALESCE(@UsersList +', ','') + Partn FROM teszt;") sCommand.SqlStatements.Add("SELECT @UsersList AS UsersList;") sCommand.Execute() connection.Close() End Sub Sub CmdE(ByVal sender As System.Object, ByVal e As CommandExecutedEventArgs) If e.StatementType = 63 Then DataGridView1.Rows.Clear() Dim Table As List(Of DataGridViewRow) = New List(Of DataGridViewRow) Dim FBDR As FbDataReader = e.DataReader While FBDR.Read() Dim adatok(FBDR.FieldCount - 1) As String For i = 0 To FBDR.FieldCount - 1 adatok(i) = FBDR(i).ToString Next Table.Add(New DataGridViewRow()) Table(Table.Count - 1).CreateCells(DataGridView1, adatok) End While DataGridView1.Rows.AddRange(Table.ToArray) End If End Sub End Class

    A kikommentezett sorok esetén lefut szépen minden, de a declare-s rész esetében már hibát dob a sCommand.Execute() utasításra.
    Hiba üzenete: "The type of the SQL statement could not be determinated."
    Mutasd a teljes hozzászólást!
  • Akkor most megismételném magam, kiemelve a lényeget.

    Tehát olyan embedded adatbázisra lenne szükségem, amelyben csak adatbázis utasításokkal megoldható az a lekérdezés ami a fentebb említett oldalon is van.
    Mutasd a teljes hozzászólást!
  • Bocsi, de kételkedem, hogy e példa lehet a döntő egy adatbáziskezelő kiválasztásában.
    Ez a feladat VB kóddal is megoldható.
    Kiadsz egy sima select-et a datareader-nek
    Select UserName FROM Users
    Majd egy ciklussal egymás mellé passzítod egy változóba (és szűröd a Null értékeket).
    Tévednék?
    Mutasd a teljes hozzászólást!
  • fb és a mysql biztosan képes erre.
    Mutasd a teljes hozzászólást!
abcd