29. august 2000 - 15:24Der er
17 kommentarer og 1 løsning
For lidt pladsallokering i ASP ved nye RS-obj?
Jeg har et problem når jeg prøver at oprette nye recordsets i ASP i en MySQL-database. Jeg har lavet et object af typen ADODB.RecordSet og åbnet det med forbindelse til min database via en sql-sætning lydende \"Select * from TestDB where id = 1\"
Databasen TestDB indeholder to felter - ID som er en integer og autonummerering (her er ingen problem), og så et felt kaldet Titel som er af typen varchar(50) - dvs. den må være op til 50 karakterer.
Nu laver jeg så en RS.AddNew, fordi jeg gerne vil lave et nyt recordset. Den fra sql-sætningen udtrukne recordsæt indeholder en Titel med længden 8 karakterer (men må jo være op til 50). Med det nye RS skriver jeg nu RS(\"Titel\") = \"abcd efgh\" (altså 9 karakterer), men dette giver en fejl. Fejlen jeg får siger mig ikke noget, for den siger bare \"Errors occurred\". Men efter længere tid har jeg fundet ud af at såfremt jeg holder mig under (eller lig) antallet af karakterer i den post, dvs. pt. 8 karakterer, så er der ingen problemer. Opretter jeg et felt databasen via en rå sql-streng, som indeholder en Titel på f.eks. 40 karakterer, og åbner databasen/RS\'et med den post istedet for, så kan jeg lave nye objekter optil 40 karakterer, men altså ikke de 50 som jeg har specificeret i felt-definitionen. På en måde knytter det sig altså til det object jeg åbner db\'en med. Jeg har prøvet adskillige ting, bl.a. også alle mulige andre felttyper på Titel-feltet - f.eks. Char(50), Text, m.v.
Alternativt er at jeg skal til at oprette (og editere eksisterende faktisk også!) poster via rå sql-sætninger, og så mister jeg jo det brugervenlige princip med at man kan sige RS(\"Titel\") = \"blabla\" RS.Update
Her er min lille testkode (for jeg troede det var min eksisterende database det var galt med, så jeg lavede en helt ny for at finde fejlen): ---- Set RS = Server.CreateObject(\"ADODB.RecordSet\") sql = \"SELECT * FROM TestDB where id=1\" %><!-- #include file=DatabaseConnection.asp --><% RS.Open sql, conn, adOpenStatic, adLockOptimistic, adCmdText
Jo, og det er når jeg sætter RS(\"Titel\") lig med en streng der er større end det der blev \"allokkeret\" (eller hvad fejlen nu skyldes), men stadig mindre en de 50 defineret i tabeldefinitionen.
Har du husket at inkludere adovbs.inc. Hvis ikke så er parametrene adOpenStatic, adLockOptimistic og adCmdText ukendte. Du kan i stedet bruger ,RS.Open sql,conn,3,3,1
Undskyld jeg svarer lidt spydigt :o), men selvfølgelig har jeg det, ellers ville 1: fejlen opstå allerede ved åbning af databasen 2: indsættelser af poster under 8 karakterer jo ikke gå godt (som de gør)
Ja ja, svin mig bare til...:-) Nej, jeg sidder og tænker på noget med om det kunne have noget at gøre med Widechar, Bytechar contra MySql o.s.v., men som regel ligger problemet i noget mere simpelt, derfor spørger jeg dig om de ting er i orden. Jeg havde heller ikke fået fat i at, det faktisk fungerer delvist. Hvis du udskriver din tabeldefinition, viser den så stadig varchar(50)? Når jeg kigger i MySql Manualen, så er VarChar defineret således at den kun fylder det antal tegn (+1), som er lagret i feltet. Char fylder altid den definerede længde. Derfor bør det fungerer, med mindre der er noget andet vi har overset..
Hvis jeg udskriver tabeldefinitionen, så viser den stadig varchar(50). Idéen med varchar er jo at den ikke FYLDER mere end det som står i feltet, men den kan dynamisk udvides til at fylde op til 50 karakterer. Modsat en char(50), som altid vil fylde 50 karakterer om så de bliver brugt eller ej. (kan være jeg tager fejl, men sådan har jeg vist lært det, hvis jeg husker ret :)).
Men ikke desto mindre, så har jeg (som tidligere beskrevet) prøvet at definere feltet til at være en del andre ting, såsom char, text osv., men uden det hjælper. Der er jo ingen problemer når jeg indsætter posten ved at skrive en rå sql-sætning, så mit gæt er at det må have noget med kombinationen af ASP at gøre?
Til en lille information skal det måske siges, at det er et website som tidligere har kørt på Access-databaser, som skal ligges over i MySQL. Så alle sider har kørt udemærket inden da. JFYI :)
Det slår mig pludselig, hvorfor åbner du tabellen og finder en bestemt post, når du alligevle, bare skal indsætte en ny. Prøv i stedet at åbne tabellen således. RS.Open \"TestDB\", adOpenKeyset, adLockOptimistic, adCmdTable
Det gør jeg fordi jeg ikke vidste man kunne åbne den som du har vist - det er hvad man får ud af at selvlære ting ved kigge i andres sources :)
Grunden til at jeg taget en bestemt post ud, er for at mindste indholdet af RS\'en. Ellers vil den jo indeholde hele tabellens indhold, så det er vel et spørgsmål om performance.
Men for nu at svare på din løsning, så virkede det desværre ikke :( Jeg tilføjede lige en \", conn\" i sætningen, men det virker ikke. Jeg sad ellers lige og håbede, da det virkede sandsynligt... I dit tilfælde fylder den også alt indholdet fra DB\'en ind i RS\'et, og der sker her det at den finder de før 8 karakterer, ud fra den post der har den største værdi. Så altså indeholder DB\'en Titler á 8, 17, 5 og 13 karakterer - så kan jeg maximalt indsætte 17 karakterer nu (og stadig ikke 50).
Det er altså kryptisk underligt det her, og det BURDE virke, men gør det ikke :(
Jeps, det er pt. også eneste udvej jeg kan se, men løser ikke mit egentlig problem som jeg helst vil have det løst, så jeg venter lige lidt og ser om der kommer andre svar på spørgsmålet...
Der er to grunde til at vælge rene sql-kald fremfor recordset: 1) Du undgår kompabilitetsproblemer mellem ADO og ODBC 2) Du vil opleve et stort performance skub i den rigtige retning
Det kræver en uddybning (følgende er erfaringer jeg har gjort mig efter mange timer dybt begravet i logfiler):
ad 1) Microsoft\'s ADO.Recordset overholder sjovt nok ikke helt standarderne omkring ODBC 2.0. Vanen tro er der lavet særlige funktioner, som ADO benytter sig af, hvis ODBC-driveren hedder SQL-server eller JET... Det går tydeligvis ud over andre databaser der overholder ODBC-standarden, som man vælger at tilgå via ADO.Recordset. Jeg har f.eks. oplevet at felter af typen TEXT ikke må være tomme eller NULL, når jeg retter en record.
ad 2) Hvis du har en tabel, som den du beskriver overfor, og laver en opdatering af en eksisterende record (id=5 og titel=\"qwe\") via recordset, genererer ADO følgende SQL sætning:
\"update testdb set id=5 and titel=\'blabla\' where (id=5 and titel=\'qwe\');\"
Kan du se problemet i ovenstående sætning? \"id\" er din primære nøgle, derfor behøver titel IKKE indgå i where-sætningen. Forestil dig nu en tabel med 20 tekst-felter nogle af typen VARCHAR og andre af typen TEXT. Der bliver kastet ret meget unødig data rundt - de vil alle blive brugt i where-sætningen (tro mig - jeg har prøvet det!)
Derfor: Brug altid Connection til indsættelse og opdatering. Brug kun recordset til udtræk - og opret dem altid implicit:
set rs = conn.execute(\"select .....\")
Dermed ikke sagt at det skal være besværligt :-) Lav en include fil, med nogle hjælpefunktioner, som kan generere sqlsætningerne for dig. Email mig privat, hvis du skal ha\' hjælp med sådan nogle hjælpe funktioner.
Da der ikke er nogen løsning på mit problem, udover det som jeg selv kunne have svaret, samt at sitet gik i luften igår, så må jeg desværre tildele mig selv pointsene (hvis jeg kan).
Jeg ved godt at RecordSets giver dårligere performance, men de er nemmere at arbejde, og når jeg nu havde et eksisterende site hvor der VAR brugt RecordSets istedet for rene sql-kald, så er det altså langt at foretrække en løsning på problemet (hvis der bare var noget). Men da det hele nu er konverteret til rene sql-sætninger, og der ikke kom nogen løsning jeg kunne bruge, så lukker jeg spørgsmålet - tak for hjælpen til dem som har forsøgt... :)
Ja, det vil jeg nok også sige - vi har givet dig en løsning. Løsningen var ikke med Recordset, da diskussionen meget tidligt konstaterede at det ikke kan lade sig gøre pga. en bug i recordsets. Men en løsning var der.
Hvad vil du have? Skulle vi grave C++ compileren frem, stjæle Microsoft\'s kildekode og skrive en bugfix til dig?
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.