Avatar billede nzc Nybegynder
19. januar 2003 - 01:01 Der er 40 kommentarer og
1 løsning

underlig SQL error

Hej

jeg prøver på at få filnavne lagt ned i en access database. min kode ser således ud (har skåret lidt af :):

        File fil = new File(dir);

        File[] filerIDir = fil.listFiles(); // et array af filer i mappen "dir" oprettes

        for (int i = 0; i < filerIDir.length; i++)
        {
            if (filerIDir[i].isDirectory() == true)
            {
                dirSize(filerIDir[i].getAbsolutePath());
            }
            else
            {
                String navn = filerIDir[i].getName();
                String sti = filerIDir[i].getAbsolutePath();
                System.out.println(navn);
                String query = "INSERT INTO filer(fil, sti) VALUES('"+navn+"','"+sti+"')";

                try
                {
                    insert.executeUpdate(query);
                }
                catch (SQLException e)
                {
                    System.out.println("fejl ved indsættelse i filer " + e.getErrorCode() + ":" + e.getSQLState() + ":" + e.getMessage());
                }

            }

        }

funktionen hedder dirsize. mit problem er at jeg ved nogle filer får denne fejlmeddelse:

fejl ved indsættelse i filer 0:null:Invalid handle

det er feks filer med navne som:

flashget_1.40.rar
IsoBuster.v1.1.rar
Total_Commander_5.5.rar

jeg forstår ikke helt hva fejlen er for noget og hvorfor den kommer for den kommer ikke ved filer som:

_ISDel.exe
_Setup.dll
_sys1.cab

og de ligner jo (karaktermæsigt) de andre

Håber i kan hjælpe :)

ov forresten hvordan får man et filnavn der hedder
kim's hat.jpg
ned i db? Den lille ' giver nemlig fejl i SQL-strengen :/ Ska jeg lave en løkke der søger strengen igennem efter ' og erstatter dem med ´ eller er der en nemmere måde ?

så har jeg ikke mere :)

på forhånd tak

NZC
Avatar billede erikjacobsen Ekspert
19. januar 2003 - 01:04 #1
Hvor lange er dine felter? Access har det med at brokke
sig hvis du fx indsætter 30 tegn i et felt på 20 tegn

Du kan erstatte alle forekomster af een ' med to, dvs: ''
Avatar billede erikjacobsen Ekspert
19. januar 2003 - 01:05 #2
Men til det sidste: bruge PreparedStatement i stedet for:
http://java.sun.com/j2se/1.4.1/docs/api/java/sql/PreparedStatement.html
Avatar billede nzc Nybegynder
19. januar 2003 - 01:06 #3
jeg bruger memo eller notat som det hedder i access DK :) og den ka indeholde en masse så vidt jeg ved.

du mener asso at en for-løkke der render filnavnet igennem er en ide ?
Avatar billede erikjacobsen Ekspert
19. januar 2003 - 01:12 #4
Så skal jeg ikke kunne sige hvorfor - prøv evt et
anden databasesystem ;)

Du *bør* bruge PreparedStatement
Avatar billede arne_v Ekspert
19. januar 2003 - 10:59 #5
Prøv lige med:

                try
                {
                    System.out.println(query);
                    insert.executeUpdate(query);
                }
                catch (SQLException e)
                {
                    e.printStackTrace();
                }

og lad os se output.
Avatar billede arne_v Ekspert
19. januar 2003 - 11:01 #6
Og Erik har ret m.h.t. at preparedStatement løser problemet
med strenge med quotes i.
Avatar billede nzc Nybegynder
19. januar 2003 - 12:47 #7
her er resultatet af system.out.print

INSERT INTO filer(fil) VALUES('Powerquest.Partition.Magic.EN.v8.0.1242.zip')
fejl ved indsættelse i filer 0:null:Invalid handle

der er blot en af dem der gir fejl.

jeg prøver lige det med prepared statements :)
Avatar billede nzc Nybegynder
19. januar 2003 - 12:53 #8
er det så sådan her man bruger prepared statements

PreparedStatement pstmt = con.prepareStatement("INSERT INTO filer(fil) VALUES('?')");

eller?

Jeg bruger jo Strings og pstmt.setString() tager en int og en String ind. Hva er int'en for noget ?
Avatar billede erikjacobsen Ekspert
19. januar 2003 - 12:53 #9
Med fare for at lyde dum :) - men er du sikker på det
er et notat-felt og ikke et text-felt på 20 tegn ?
Avatar billede erikjacobsen Ekspert
19. januar 2003 - 12:54 #10
PreparedStatement pstmt = con.prepareStatement("INSERT INTO filer(fil) VALUES(?)");

og så setString med dit filnavn
Avatar billede erikjacobsen Ekspert
19. januar 2003 - 12:55 #11
Nå ja, tallet (int-en) er nummeret på spørgsmålstegnet. Du skal skrive
1 - der er jo kun det samme
Avatar billede nzc Nybegynder
19. januar 2003 - 13:02 #12
jeg har lige ændret felterne i db til tekststrenge på 255 :) så nu er jeg sikker på at de er store nok :)

når jeg vil execute mit pstmt er det så

pstmt.executeUpdate();

?
Avatar billede arne_v Ekspert
19. januar 2003 - 13:15 #13
Ja - det er excecuteUpdate uden argument, fordi du angiver SQL i
prepareStement og værdi i setString.
Avatar billede arne_v Ekspert
19. januar 2003 - 13:15 #14
Og jeg kunne staadigvæk godt tænke mig at se den fulde
printStackTrace.
Avatar billede arne_v Ekspert
19. januar 2003 - 13:18 #15
Umiddelbart lyder fjelen nemlig ikek som det har noget med hverken
værdi eller feltets datatype at gøre.

Men snarere som om forbindelsen til databasen er væk.
Avatar billede nzc Nybegynder
19. januar 2003 - 13:25 #16
nu har jeg jo ændret en masse i programmet og nu virker det slet ikke :(

men printstacktrace giver
java.sql.SQLException: General error
    at sun.jdbc.odbc.JdbcOdbc.throwGenericSQLException(JdbcOdbc.java:7008)
    at sun.jdbc.odbc.JdbcOdbc.SQLAllocStmt(JdbcOdbc.java:174)
    at sun.jdbc.odbc.JdbcOdbcConnection.prepareStatement(JdbcOdbcConnection.java:465)
    at sun.jdbc.odbc.JdbcOdbcConnection.prepareStatement(JdbcOdbcConnection.java:443)

nu vil den slet ikke indsætte noget som helst i db
Avatar billede erikjacobsen Ekspert
19. januar 2003 - 13:29 #17
Din kode?
Avatar billede arne_v Ekspert
19. januar 2003 - 13:30 #18
File fil = new File(dir);

        PreparedStatement pstmt = con.prepareStatement("INSERT INTO filer(fil) VALUES('?')");

        File[] filerIDir = fil.listFiles();

        for (int i = 0; i < filerIDir.length; i++)
        {
            if (filerIDir[i].isDirectory() == true)
            {
                dirSize(filerIDir[i].getAbsolutePath());
            }
            else
            {
                String navn = filerIDir[i].getName();
                String sti = filerIDir[i].getAbsolutePath();
                System.out.println(navn);
                try
                {
                    pstmt.setString(1, navn);
                    pstmt.executeUpdate();
                }
                catch (SQLException e)
                {
                    e.printStackTrace();
                }

            }

        }

?
Avatar billede nzc Nybegynder
19. januar 2003 - 13:33 #19
import java.io.File;
import java.awt.*;
import java.sql.*;

public class filtest
{
    private static Connection con;
    private static PreparedStatement pstmt;

    public static void dirSize(String dir)
    {

        try
        {
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        }
        catch (Exception e)
        {
            System.out.println("Failed to load JDBC/ODBC driver.");
        }
        try
        {
            con = DriverManager.getConnection("jdbc:odbc:filer", "", "");


        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        long res = 0;

        File fil = new File(dir);

        File[] filerIDir = fil.listFiles(); // et array af filer i mappen "dir" oprettes

        for (int i = 0; i < filerIDir.length; i++)
        {
            if (filerIDir[i].isDirectory() == true)
            {
                dirSize(filerIDir[i].getAbsolutePath());
            }
            else
            {
                String navn = filerIDir[i].getName();
                try
                {
                    pstmt = con.prepareStatement("INSERT INTO filer(fil) VALUES(?)");
                    pstmt.setString(1, navn);


                    pstmt.executeUpdate();
                }
                catch (SQLException e)
                {
                      e.printStackTrace();
                }

            }

        }

        /* Lav en løkke der løber igennem filerIDir, og undersøger hver eneste fil.
        Hvis det er en mappe skal metoden kalde sig selv og tælle res op med en hel
        mappes indhold, hvis det er en "normal" fil skal res blot tælles op. */
        try
        {
            pstmt.close();
            con.close();
        }
        catch (SQLException se)
        {
            System.out.println(se);
        }
    }
Avatar billede arne_v Ekspert
19. januar 2003 - 13:35 #20
Det er ikke skyld i fejlen, men

pstmt = con.prepareStatement("INSERT INTO filer(fil) VALUES(?)");

bør flyttes udenfor for-løkken.
Avatar billede arne_v Ekspert
19. januar 2003 - 13:38 #21
JDBC ODBC bridgen kan iøvrigt godt drille lidt.

Så prøv evt. en klassisk løsning: luk ned, reboot PC og prøv igen.
Avatar billede nzc Nybegynder
19. januar 2003 - 13:56 #22
hmmm har lige rebootet

pstmt.setString(1, navn); <--- den udløser den her
java.sql.SQLException: Invalid handle
    at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7051)
    at sun.jdbc.odbc.JdbcOdbc.SQLBindInParameterString(JdbcOdbc.java:980)
    at sun.jdbc.odbc.JdbcOdbcPreparedStatement.setChar(JdbcOdbcPreparedStatement.java:3106)
    at sun.jdbc.odbc.JdbcOdbcPreparedStatement.setString(JdbcOdbcPreparedStatement.java:764)

hjælp ?!
Avatar billede erikjacobsen Ekspert
19. januar 2003 - 14:05 #23
Det er heller ikke særlig smart at åbne en
forbindelse for hvert rekursivt kald.
Det bør du kun gøre én gang.
Avatar billede nzc Nybegynder
19. januar 2003 - 14:06 #24
ye det ved jeg godt :)

men det er blot en lille test
Avatar billede arne_v Ekspert
19. januar 2003 - 14:13 #25
Erik du har fundet problemet !

con er static !!

Så når man kalder rekursivt laver man en ny con som bliver closet
og så returnerer man tilbage og bruger con igen !!!
Avatar billede arne_v Ekspert
19. januar 2003 - 14:15 #26
import java.io.File;
import java.awt.*;
import java.sql.*;

public class filtest
{
    private static Connection con = null;
    private static PreparedStatement pstmt;

    public static void dirSize(String dir)
    {
      if(conn == null) {
        try
        {
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        }
        catch (Exception e)
        {
            System.out.println("Failed to load JDBC/ODBC driver.");
        }
        try
        {
            con = DriverManager.getConnection("jdbc:odbc:filer", "", "");
            pstmt = con.prepareStatement("INSERT INTO filer(fil) VALUES(?)");


        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        }
        long res = 0;

        File fil = new File(dir);

        File[] filerIDir = fil.listFiles(); // et array af filer i mappen "dir" oprettes

        for (int i = 0; i < filerIDir.length; i++)
        {
            if (filerIDir[i].isDirectory() == true)
            {
                dirSize(filerIDir[i].getAbsolutePath());
            }
            else
            {
                String navn = filerIDir[i].getName();
                try
                {
                    pstmt.setString(1, navn);


                    pstmt.executeUpdate();
                }
                catch (SQLException e)
                {
                      e.printStackTrace();
                }

            }

        }


    }
Avatar billede arne_v Ekspert
19. januar 2003 - 14:18 #27
Jeg har lige omformateret koden lidt:

import java.io.File;
import java.awt.*;
import java.sql.*;

public class FilTest {
    private static Connection con = null;
    private static PreparedStatement pstmt;

    public static void dirSize(String dir) {
        if (con == null) {
            try {
                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            } catch (Exception e) {
                System.out.println("Failed to load JDBC/ODBC driver.");
            }
            try {
                con = DriverManager.getConnection("jdbc:odbc:filer", "", "");
                pstmt =
                    con.prepareStatement("INSERT INTO filer(fil) VALUES(?)");

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        long res = 0;

        File fil = new File(dir);

        File[] filerIDir = fil.listFiles();

        for (int i = 0; i < filerIDir.length; i++) {
            if (filerIDir[i].isDirectory() == true) {
                dirSize(filerIDir[i].getAbsolutePath());
            } else {
                String navn = filerIDir[i].getName();
                try {
                    pstmt.setString(1, navn);

                    pstmt.executeUpdate();
                } catch (SQLException e) {
                    e.printStackTrace();
                }

            }

        }

    }
}
Avatar billede nzc Nybegynder
19. januar 2003 - 14:21 #28
aaaaaahhhhh

mange tak for tålmodigheden :)

hvis nu jeg vil bruge en mysql db i stedet, kender i så et godt stedd til en lille tutorial eller ka i lige slynge en løsning ud ?

Jeg har oprettet mysql-db'en men mangler forbindelse til den

Mange tak

NZC
Avatar billede arne_v Ekspert
19. januar 2003 - 14:23 #29
Du skal kun rette 2 linier for at skifte fra Access til MySQL:

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

skal rettes til for at bruge MySQL JDBC driver.

con = DriverManager.getConnection("jdbc:odbc:filer", "", "");

skal rettss til for at bruge MySQL URL.
Avatar billede arne_v Ekspert
19. januar 2003 - 14:25 #30
MySQL driver er:
  com.mysql.jdbc.Driver

MySQL URL syntax er:
  jdbc:mysql://hostnavn/databasenavn
Avatar billede nzc Nybegynder
19. januar 2003 - 14:29 #31
tester det lige :)

Mange tak
Avatar billede arne_v Ekspert
19. januar 2003 - 14:32 #32
Vær lige opmærksom på, at MySQL JDBC driver skal downloades
separat (kommer ikek sammen med selve MySQL).

Og i modsætning til JDBC ODBC bridge der altid er i classpath, så skal
MySQL JDBC JAR filen eksplicit anbrindes i classpath.
Avatar billede nzc Nybegynder
19. januar 2003 - 14:44 #33
jeg ska oprette min db i data source og mysql-driveren kræver windows DNS. jeg er den største n00b hva netværk og DNS angår :)

hva er det lige windows DNS er og hvor ka jeg se det henne ?
Avatar billede nzc Nybegynder
19. januar 2003 - 14:45 #34
hehe havde ikke refreshet :)
Avatar billede arne_v Ekspert
19. januar 2003 - 14:46 #35
Lad være med at bruge MySQL ODBC driver og JDBC ODBC bridge.

Download mySQL JDBC driver, udpak den og brug den.
Avatar billede nzc Nybegynder
19. januar 2003 - 14:49 #36
den bruger jeg sådan her ?

MySQL driver er:
  com.mysql.jdbc.Driver

MySQL URL syntax er:
  jdbc:mysql://hostnavn/databasenavn

?
Avatar billede arne_v Ekspert
19. januar 2003 - 14:53 #37
Class.forName("com.mysql.jdbc.Driver");
...
con = DriverManager.getConnection("jdbc:mysql://hostnavn/databasenavn", "", "");
Avatar billede nzc Nybegynder
19. januar 2003 - 15:01 #38
hmm

den her con = DriverManager.getConnection("jdbc:mysql://localhost/filer", "root", "");

er skyld i den her

java.sql.SQLException: No suitable driver
    at java.sql.DriverManager.getConnection(DriverManager.java:532)
    at java.sql.DriverManager.getConnection(DriverManager.java:171)

jeg har pakket .jar-filen ud og lagt mm.mysql-2.0.14-bin.jar i min class-path som README'en siger
Avatar billede arne_v Ekspert
19. januar 2003 - 15:05 #39
Ah.

Der er 2 forskellige JDBC drivere til MySQL.

Jeg bruger den der er i mysql-connector-java-2.0.14-bin.jar !

Driveren hedder noget andet i den du har.
Avatar billede arne_v Ekspert
19. januar 2003 - 15:06 #40
Brug:
  org.gjt.mm.mysql.Driver
Avatar billede nzc Nybegynder
19. januar 2003 - 16:00 #41
sådan så virker det med mysql :)

mange tak arne_v :))))

NZC
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester