ResultSet-Ergebnis mit INSERT in Tabelle schreiben

Programmierung mit PostgreSQL (C#, PHP, Perl, Java, ...)

ResultSet-Ergebnis mit INSERT in Tabelle schreiben

Beitragvon Scheff » Mi 2. Jul 2008, 16:08

Hallo Gemeinde,
ich möchte mit einem Java-Programm ein mit ResultSet erzeugtes Ergebnis aus einer Tabelle in eine andere Tabelle schreiben.
Hier mein Java-Code:

[size=75] [size=84]public static void Abfrage()
{
try
{
stmt = con.createStatement();
String abfragen = "SELECT * FROM auftragsplanung ";
ResultSet rs = stmt.executeQuery(abfragen); //Abfrage aus Tabelle auftragsplanung

/* daten durchlaufen */
while (rs.next())
{
String Folie = rs.getString(9); //Spalte (9) ist Deckelfolie!
Integer Verbrauch = rs.getInt(4); //Spalte (4) ist Stückzahl!
System.out.print(Folie); System.out.println(" "+Verbrauch);
//Abgefragte Werte einsetzen in Tabelle tab1
String einsetzen = "INSERT INTO tab1 (folie,verbrauch)
VALUES("+Folie+","+Verbrauch+")";
stmt.executeUpdate(einsetzen);
}
}
catch (Exception e)
{
System.out.println("PG-Fehler: " + e.getMessage());
}
}
Als Fehlermeldung von postgres bekomme ich das:

[size=84]ec@linux:~/Postgres/Daten> java testfolie
Verbunden mit: jdbc :p ostgresql://localhost/Auftrag/
hs1250x0,135 121
PG-Fehler: FEHLER: Spalte »hs1250x0« existiert nicht
Tabelle ist geschlossen
ec@linux:~/Postgres/Daten>
[/size][/size]
Die erste Zeile des ResultSets wird durch die Print-Befehle noch angezeigt. Dann entsteht offenbar beim Zugriff auf die Tabelle tab1 ein
Fehler, der dann geworfen wird.
Was ist an dieser Konstruktion faul und wie muß es richtig heißen?
Schon mal vielen Dank für Eure Mitarbeit,
Gruß Scheff
[/size]
Scheff
Neuer Benutzer
 
Beiträge: 6
Registriert: Mo 30. Jun 2008, 11:00

Beitragvon akretschmer » Mi 2. Jul 2008, 16:18

Scheff hat geschrieben:Hallo Gemeinde,
ich möchte mit einem Java-Programm ein mit ResultSet erzeugtes Ergebnis aus einer Tabelle in eine andere Tabelle schreiben.
Hier mein Java-Code:

[size=75] [size=84]public static void Abfrage()
{
try
{
stmt = con.createStatement();
String abfragen = "SELECT * FROM auftragsplanung ";
ResultSet rs = stmt.executeQuery(abfragen); //Abfrage aus Tabelle auftragsplanung

/* daten durchlaufen */
while (rs.next())
{
String Folie = rs.getString(9); //Spalte (9) ist Deckelfolie!
Integer Verbrauch = rs.getInt(4); //Spalte (4) ist Stückzahl!
System.out.print(Folie); System.out.println(" "+Verbrauch);
//Abgefragte Werte einsetzen in Tabelle tab1
String einsetzen = "INSERT INTO tab1 (folie,verbrauch)
VALUES("+Folie+","+Verbrauch+")";
stmt.executeUpdate(einsetzen);
}
}
catch (Exception e)
{
System.out.println("PG-Fehler: " + e.getMessage());
}
}
Als Fehlermeldung von postgres bekomme ich das:

[size=84]ec@linux:~/Postgres/Daten> java testfolie
Verbunden mit: jdbc :p ostgresql://localhost/Auftrag/
hs1250x0,135 121
PG-Fehler: FEHLER: Spalte »hs1250x0« existiert nicht
Tabelle ist geschlossen
ec@linux:~/Postgres/Daten>
[/size][/size]
Die erste Zeile des ResultSets wird durch die Print-Befehle noch angezeigt. Dann entsteht offenbar beim Zugriff auf die Tabelle tab1 ein
Fehler, der dann geworfen wird.
Was ist an dieser Konstruktion faul und wie muß es richtig heißen?
Schon mal vielen Dank für Eure Mitarbeit,
Gruß Scheff
[/size]


Da sind mehrere Fehler. Zum einen, ein SELECT * ist böse. Zum anderen, auf einzelne Spalten via der (vermuteten) Nummer zuzugreifen. Beides fällt Dir schmerzhaft auf die Füße, wenn sich die Tabellenstruktur mal ändert.

Der eigentliche Fehler dürfte aber " statt ' bei VALUES("+Folie+","+Verbrauch+")"; sein.

Im übrigen: Deine Methode, so durch ein Resultat zu latschen und Record für Record vom Server auf den Client zu zerren, um ihn dann wieder woanders einfügen zu können, ist eine schlechte Idee: Du kannst das auch direkt via insert ... select machen. Das geht um etliche zehnerpotenzen dann schneller.


Andreas
--
ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)

https://www.xing.com/profile/Andreas_Kretschmer7
Hosting-Provider mit PostgreSQL-Support gesucht? Mich fragen!
akretschmer
Erfahrener Benutzer
 
Beiträge: 5936
Registriert: So 29. Okt 2006, 14:35
Wohnort: Kaufbach, Sachsen, Germany, Germany

Beitragvon Scheff » Mi 2. Jul 2008, 16:48

Hallo Andreas, vielen Dank für die prompte Antwort.
Dein Tip mit den einfachen Apostrophen anstatt den doppelten hat nichts gebracht. Der
Compiler macht dann natürlich aus meiner int-Variablen eine Text-Variable, die er an dieser Stelle natürlich nicht in die Tabelle einfügen kann.
Nochmal der abgeänderte Code:

public static void Abfrage()
{
try
{
stmt = con.createStatement();
String abfragen = "SELECT * FROM auftragsplanung ";
ResultSet rs = stmt.executeQuery(abfragen); //Abfrage aus Tabelle auftragsplanung

/* daten durchlaufen */
while (rs.next())
{
String Folie = rs.getString(9); //Spalte (9) ist Deckelfolie!
Integer Verbrauch = rs.getInt(4); //Spalte (4) ist Stückzahl!
System.out.print(Folie); System.out.println(" "+Verbrauch);
//Abgefragte Werte einsetzen in Tabelle tab1
//String einsetzen = "INSERT INTO tab1 (folie,verbrauch) VALUES("+Folie+","+Verbrauch+")";
String einsetzen = "INSERT INTO tab1 (folie,verbrauch) VALUES('+Folie+','+Verbrauch+')";
stmt.executeUpdate(einsetzen);
}
}
catch (Exception e)
{
System.out.println("PG-Fehler: " + e.getMessage());
}
}
Mit zugehöriger Fehlermeldung:

ec@linux:~/Postgres/Daten> java testfolie

Verbunden mit: jdbc :p ostgresql://localhost/Auftrag/

hs1250x0,135 121
PG-Fehler: FEHLER: ungültige Eingabesyntax für ganze Zahl: »+Verbrauch+«
Tabelle ist geschlossen

Das Programm werde ich später noch optimieren, aber in dieser Testphase will ich erst mal die INSERT-Konstruktion zum Laufen bringen.
Zum besseren Verständnis vielleicht noch die Struktur der beiben Tabellen:
Auftrag=# \d auftragsplanung
Tabelle »public.auftragsplanung«
Spalte | Typ | Attribute
--------------+------------------------+-------------------------------------------------------------------------
Auftrags-ID | integer | not null default nextval('"Auftragsplanung_Auftrags-ID_seq"'::regclass)
Auftrags-Nr | character varying(255) |
Kunde | character varying(255) |
Stückzahl | bigint |
Termin | character varying(255) |
Abmessung | character varying(255) |
Haubenlänge | bigint |
Haubenbreite | bigint |
Deckelfolie | character varying(255) |
Umfangsfolie | character varying(255) |
Foliendicke | real |
Bemerkung | character varying(255) |
Indexe:
»Auftragsplanung_pkey« PRIMARY KEY, btree ("Auftrags-ID")


Auftrag=# \d tab1
Tabelle »public.tab1«
Spalte | Typ | Attribute
-----------+-------------------+-----------
folie | character varying |
verbrauch | integer |

Auftrag=#

Ich will daraus die Spalten Deckelfolie, Stückzahl respektive Umfangsfolie, Stückzahl
in den beiden Spalten folie, verbrauch untereinander schreiben, weil ich daraus später für eine Lagerliste die verbrauchten Folienmengen berechnen will.

Gruß Scheff
Scheff
Neuer Benutzer
 
Beiträge: 6
Registriert: Mo 30. Jun 2008, 11:00

Beitragvon symbiont » Do 3. Jul 2008, 08:57

akretschmer hat geschrieben:
Der eigentliche Fehler dürfte aber " statt ' bei VALUES("+Folie+","+Verbrauch+")"; sein.

...
Andreas


Die " sind in diesem Fall Java-Quotes für Java Strings .. also der String sieht dann so aus :

" ... VALUES("+Folie+", "+Verbrauch+")"[color=Black];[/color]

Schwarz sind die Variablen die er vorher gefüllt hat .. Also die vorherige Variante war schon beinahe OK - wenn man annimmt, dass Folie ein String und Verbrauch Integer ist müsste es so richtig sein.

" ... VALUES([color=Blue]
[/color][color=Blue]'[/color]"+Folie+"[color=Blue]'[/color], "+Verbrauch+")"[color=Black];

[/color]
Der besagte Fehler
PG-Fehler: FEHLER: ungültige Eingabesyntax für ganze Zahl: »+Verbrauch+«

kann viele Ursachen haben .. dazu wäre es gut, wenn du (Scheff) mal den Stacktrace der PLSQLException schicken wuerdest.

Sind Trigger auf den Tabellen deren Funktionen den Fehler verursachen koennten?

Gruß
Steffen
symbiont
Erfahrener Benutzer
 
Beiträge: 1328
Registriert: Mo 17. Mär 2008, 12:45
Wohnort: NULL

Beitragvon akretschmer » Do 3. Jul 2008, 09:07

symbiont hat geschrieben:Die " sind in diesem Fall Java-Quotes für Java Strings .. also der String sieht dann so aus :



Danke für die Richtigstellung.

Andreas
--
ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)

https://www.xing.com/profile/Andreas_Kretschmer7
Hosting-Provider mit PostgreSQL-Support gesucht? Mich fragen!
akretschmer
Erfahrener Benutzer
 
Beiträge: 5936
Registriert: So 29. Okt 2006, 14:35
Wohnort: Kaufbach, Sachsen, Germany, Germany

Beitragvon Scheff » Do 3. Jul 2008, 12:47

Hallo symbiont und Andreas,
IHR SEID SPITZE !! :) Klasse Zusammenarbeit :)
Das war wieder ein Volltreffer! :)
Eine String-Variable muß man mit dieser Syntax ' [color=Red]" [color=Black]+ x + [color=Red]" [color=Blue]'[/color] usw. übergeben. Das Programm schreibt allerdings nur den ersten Datensatz und schließt dann die Tabelle. Das liegt aber wohl nur an meiner unvorteilhaften Konstruktion. Wie Andreas schon angemerkt hat sollte man das so nicht machen.
Ich versuche jetzt den Stacktrace hinzubekommen (weiß noch nicht wie man das macht), werde den Code verbessern und melde mich dann wieder.
P.S. Kennt Ihr das Datenbank-Frontend "knoda". Damit will ich mein Auftragsprogramm aufbauen.
Vielen Dank Scheff

[/color][/color][/color]
Scheff
Neuer Benutzer
 
Beiträge: 6
Registriert: Mo 30. Jun 2008, 11:00

Beitragvon symbiont » Do 3. Jul 2008, 13:18

Scheff hat geschrieben:[color=Red][color=Black]
Ich versuche jetzt den Stacktrace hinzubekommen (weiß noch nicht wie man das macht),
...
[/color][/color]



Code: Alles auswählen
try {

... mein Fehlerhafter Code :) ..

} catch (SQLException e) {

   // Stacktrace auf der Console ausgeben ..
   e.printStackTrace();
}

den kannst du dann aus der Console kopieren und hier posten
symbiont
Erfahrener Benutzer
 
Beiträge: 1328
Registriert: Mo 17. Mär 2008, 12:45
Wohnort: NULL

Beitragvon Scheff » Do 3. Jul 2008, 14:04

Hallo symbiont,
hier der Stacktrace:
ec@localhost:~/Postgres/Daten> java testfolie
Verbunden mit: jdbc :p ostgresql://localhost/Auftrag/
hs1250x0,135 121
PG-Fehler: Dieses ResultSet ist geschlossen.
org.postgresql.util.PSQLException: Dieses ResultSet ist geschlossen.
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.checkClosed(AbstractJdbc2ResultSet.java:2585)
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.next(AbstractJdbc2ResultSet.java:1803)
at testfolie.Abfrage(testfolie.java:73)
at testfolie.main(testfolie.java:22)

damit kann ich nun gar nix anfangen! :confused:
Es ist wohl so wie Andreas schon bemerkt hat. Der Code ist so nicht gut.
Wäre ein PreparedStatement die Lösung?

Hier noch der eingefügte Datensatz in der Tabelle:

Auftrag=# select * from tab1;
folie | verbrauch
--------------+-----------
hs1250x0,135 | 121
(1 Zeile)
und der Vollständigkeit halber der komplette Java-Code:

[code]/**Datenbankprogramm testfolie.java */

import java.sql.*;

public class testfolie
{
static DatabaseMetaData dmd;
static Statement stmt;
static Connection con;
// static ResultSet resu;

public static void main(String[] args)
{
Verbinden();
Abfrage();
schliessen();
}

public static void Einfügen()
{
try
{ stmt = con.createStatement();
int Verbrauch = 1200;
String Folie = "'df2000x0,135'";
String einsetzen = "INSERT INTO tab1 (folie,verbrauch) VALUES("+Folie+","+Verbrauch+")";
for (int i=1;i<=5;++i){

stmt.executeUpdate(einsetzen); }

System.out.println("Werte sind eingefügt");
}
catch (Exception e)
{
System.out.println("Fehler: " + e.getMessage());
}
}

public static void Abfrage()
{
try
{
stmt = con.createStatement();
String abfragen = "SELECT * FROM auftragsplanung ";
ResultSet rs = stmt.executeQuery(abfragen);

while (rs.next())
{
String Folie = rs.getString(9); //Spalte (9) ist Deckelfolie!
Integer Verbrauch = rs.getInt(4); //Spalte (4) ist Stückzahl!
System.out.print(Folie); System.out.println(" "+Verbrauch);
String einsetzen = "INSERT INTO tab1 (folie,verbrauch) VALUES('"+Folie+"',"+Verbrauch+")";
stmt.executeUpdate(einsetzen);
}
}
catch (Exception e)
{
System.out.println("PG-Fehler: " + e.getMessage());
e.printStackTrace();
}
}

public static void Verbinden()
{
try
{
Class.forName("org.postgresql.Driver");
}
catch (ClassNotFoundException e)
{
System.err.println("Driver class not found");
e.printStackTrace();
} con = null;
try
{
con = (Connection) DriverManager.getConnection(
"jdbc :p ostgresql://localhost/Auftrag/","ec","");
if (con == null)
{
System.out.println("Keine Verbindung");
System.exit(1);
}
else
{
System.out.println(" ");
/**Metadaten ausgeben */
dmd = con.getMetaData();
System.out.println("Verbunden mit: "+ dmd.getURL());
System.out.println(" ");
}
}
catch (SQLException e1)
{ }
}

public static void schliessen()
{
try
{
stmt.close();
con.close();
System.out.println("Tabelle ist geschlossen");
}
catch (SQLException e)
{
Throwable t = e;
while (t != null)
{
System.err.println("Type: " + t.getClass().getName());
System.err.println("Message: " + t.getMessage());
System.err.println("-----");
t = t.getCause();
}
}
}
}

Gruß Scheff
Scheff
Neuer Benutzer
 
Beiträge: 6
Registriert: Mo 30. Jun 2008, 11:00

Wäre sicher schöner mit PreparedStatements ..

Beitragvon symbiont » Do 3. Jul 2008, 14:39

wenn der Fehler beim Schreiben auftritt, mir scheint es jedoch, der Fehler tritt auf, weil Du das gleiche java.sql.Statement für Dein executeUpdate(..) verwendest, dass Du vorher zum Öffnen des ResultSet verwendet hast.

Das heisst, das (von Statement stmt abhängige) ResultSet wird bei dem executeUpdate("INSERT ..") geschlossen so dass der Fehler bei rs.next(.) auftreten muss.


Was du eigentlich versucht hast, ist das updatefaehige Resultset zu nutzen .. ich arbeite so selbst nicht .. aber probiere mal folgenedes

statt dem executeUpdate("INSERT ..") verwendest Du
rs.updateString(index , value) um die Feldwerte zu setzen .. analog rs.updateInt(.. ) etc. und commitest die Änderungen danach mit rs.updateRow().

das Statement selbst fasst Du dabei nimmer an - ausser wenn Du mit dem Rumaendern fertig bist - das ResultSet und Statement schliessen ..

gruß

p.s. oder du erzeugst dir eine weitere Statement-Instanz für ein selbstgeneriertes INSERT incl Werten im String .. oder ein PreparedStatement mit Parametern eben .. zum "kennen-lernen" kann es nicht falsch sein, wenn du die nichtmal eine handvoll Möglichkeiten ausprobierst. Die paar Zeilen Code haben Dir ja bereits ein wenig Zeit gekostst - da kommts daraf nun auch nimmer an ..

Es ist aber immer gut zu wissen, WARUM ein Fehler aufgetreten ist - auch wenn dir jemand eine funktionierende Variante vorbetet ..
symbiont
Erfahrener Benutzer
 
Beiträge: 1328
Registriert: Mo 17. Mär 2008, 12:45
Wohnort: NULL

Nochetwas

Beitragvon symbiont » Do 3. Jul 2008, 14:50

in der JavaDoc zu java.sql.ResultSet steht:

A ResultSet object is automatically closed when the Statement object that generated it is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.


Dort findest du auch diverse Beispiele, wie ein update-fähiges Resultset zu erzeugen ist (bestimmte Parameter für Statement etc.) und vieles mehr.
symbiont
Erfahrener Benutzer
 
Beiträge: 1328
Registriert: Mo 17. Mär 2008, 12:45
Wohnort: NULL


Zurück zu Programmierung

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste