# SQL String zwei Tabellen vergleichen und gleiche Zeile löschen



## Chriss_07 (12. Jun 2010)

Ich habe zwei Tabellen Table1 Table2. Die Zeilen von Table1 werden suksessive in Table2 übergeben.
Nach dem übergeben in Table2 soll die entsprechende Zeile in Table1 gelöscht werden.
Anhand von zwei übereinstimmenden Feldern kann ich die Zeile erkennen.


```
"delete FROM Table1 WHERE value1= value1.table2 and value2 = value2.table2";
```

Das klappt so nicht und ich finde keine Anhaltspunkte.


----------



## Gast2 (12. Jun 2010)

```
DELETE FROM table1 WHERE value1 IN (SELECT value1 FROM table2)
```

Sollte es tun - zumindest auf einer ORACLE


----------



## Chriss_07 (13. Jun 2010)

Die SQL Abfrage durchläuft das Programm erfolgreich aber der Löschvorgang geht nicht.

```
DELETE FROM table1 WHERE value1 IN (SELECT value1 FROM table2) and value2 IN (SELECT value2 FROM table2)
```
Die Methode zum Löschen hängt an einem Button, zusammen mit der addMethode. Also wird mit einem Klick der Datensatz in Table2 geschrieben und danach in Table1 gelöscht.


----------



## Gast2 (13. Jun 2010)

Hast du schon mal das SQL per Hand auf der DB durchgeführt?

Bist du sicher das du ein UND willst bei den beiden Subselects?

Ist value1 oder value2 ein Primärschlüssel? Dann kannst du dir auch einen der Subselects sparen. Wenn value1||value2 ein zusammengesetzer Schlüsselist kannst du das auch mit einem Subselect machen


```
DELETE FROM table1 WHERE value1||value2 IN (SELECT value1||value2 FROM table2)
```


----------



## Chriss_07 (13. Jun 2010)

fassy hat gesagt.:


> Hast du schon mal das SQL per Hand auf der DB durchgeführt?


Erst jetzt , geht auch nicht



fassy hat gesagt.:


> Bist du sicher das du ein UND willst bei den beiden Subselects?


Jein



fassy hat gesagt.:


> Ist value1 oder value2 ein Primärschlüssel? Dann kannst du dir auch einen der Subselects sparen. Wenn value1||value2 ein zusammengesetzer Schlüsselist kannst du das auch mit einem Subselect machen


Nein, ursprünglich nicht. Wenn ich aber den PRIMAYRY KEY der Table1 verwende, dann löscht er aber die falschen Werte, da Table 2 seinen eigene ID (PRIMARY KEY) erstellt.
Table1 hat ID 1,2,3,4,5 übergibt an TAble2 die Werte mit der ID 4 - die wird in Table zwei dann zu ID 1
Und gelöscht wird ID 1 in Table 1. Daher wollte ich zwei Subselects verwenden.
Ich arbeite mit SQLite Database Browser


----------



## Gast2 (13. Jun 2010)

Das muss funktionieren - um genau zu sein habe ich es grade auch ncoh mal mit SQLite ausprobiert. Ersetz mal [c]DELETE FROM[/c] durch [c]SELECT * FROM[/c]

Mein test:


```
table1
  - id INTEGER PRIMARY KEY
  - value1 TEXT
  - value2 TEXT


table2
  - id INTEGER PRIMARY KEY
  - value1 TEXT
  - value2 TEXT

INSERT INTO table1 VALUES(1,'a1','a2');
INSERT INTO table1 VALUES(2,'b1','b2');
INSERT INTO table2 VALUES(3,'a1','a2');
INSERT INTO table2 VALUES(4,'b1','b2');

SELECT * FROM table1 WHERE value1 IN (SELECT value1 FROM table2)
=>
1, a1, a2
2, b1, b2
```

Sonst beschreib doch bitte noch mal deine beiden Tabellen...


----------



## Chriss_07 (13. Jun 2010)

fassy hat gesagt.:


> Das muss funktionieren - um genau zu sein habe ich es grade auch ncoh mal mit SQLite ausprobiert. Ersetz mal [c]DELETE FROM[/c] durch [c]SELECT * FROM[/c]




```
Select *
```
 verursacht syntax error near FROM



fassy hat gesagt.:


> Mein test:
> 
> 
> ```
> ...


----------



## Gast2 (13. Jun 2010)

```
SELECT * FROM table1 WHERE value1 IN (SELECT value1 FROM table2)
```

Muss gehen. Poste doch bitte mal die Rows in Table1 und Table2. Also was du so konkret an Testdaten da drin hast.


----------



## Chriss_07 (14. Jun 2010)

TABLE1(Feldtyp - Ursprung der Daten)
ID(PK) Zeit(TXT) Ort(TXT-ComboBox) Strasse(TXT-ComboBox) Fahrzeug(TXT-ComboBox) Info(TXT-JTextArea)

TABLE2
ID(PK) Zeit(TXT) Ort(TXT-String aus Table1) Strasse(TXT-String aus Table1) Zielort(TXT-ComboBox) Zielstrasse(TXT-ComboBox) Fahrzeug(TXT-String aus TABLE1) Kilometer(TXT-TextField) Info(TXT-String aus TABLE1)

Die Zeit wird automatisch hinterlegt( "HH:MM"). Ort, Strasse, Zielort, Zielstrasse, Fahrzeug sind MUSS Felder. Alle anderen können auch NULL oder auch leer sein.

```
public void actionPerformed(ActionEvent e) {
		if ( ((JButton)e.getSource()).getName().equals("saveBT")){
			try {
				addNewFinish(); // Fügt die Tour in TABLE2
				deleteTour();   // löscht die Tour aus TABLE1
				
			} catch (Exception e1) {
........

private void addNewFinish() throws Exception{  // Formularfelder aus Frame2 die zum tour.getsplit()[0] usw. addiert werden (stammt aus Frame1)
		
		NewFinish tour = new NewFinish();
		
		tour.setTour(frei.getTour());
		tour.setZielort(frei.getZielOrt());
		tour.setZielstrasse(frei.getZielStrasse());
		tour.setKilometer(frei.getKilometer());
		
		erfassenDB.addNewFinish(tour);
		
	}
	
	private void deleteTour() throws Exception {
		
		erfassenDB.deleteTour();  //Führt die Methode DELETE aus dem Datenbankzugriff aus
		frei.dispose();
		new NewJFrame();   // springt zurück zu Frame1 		
	}
```
 Die Datensätze werden korrekt in TABLE1 und TABLE2 geschrieben.


----------



## Gast2 (14. Jun 2010)

Wenn  du nicht den PK mit in die neue Tabelle überführst musst du halt über einen künstlichen Composite Key die Rows zusammen suchen. Würde ich bei deinem Beispiel allerdings nciht machen. Das sit einfach imperformant und nicht grade elegant. 
Insgesammt wage ich mal zu behaupten das du dir mit der Architektur keinen Gefallen tust. Ich würde eherlich gesagt beim insert von Tabelle1 in Tabelle2 die ID von 1 mit übernehmen. Entweder als eigene Spalte oder aber warum nicht direkt die ID von Tabelle2 überschreiben?

Ich versteh allerdings auch gar nicht was du genau vorhast. In Tabelle1 einfügen, dann nach Tabelle2 kopieren und in Tabelle1 wieder löschen. Das ist nicht grade ein robuster und guter Programmierstil. 

Warum nicht:
1) In Tabelle1 einfügen - Tabelle1 updaten
oder
2) In Tabelle1 Headerdatensatz einfügen und in weiteren Tabellen Details erfassen


----------



## Chriss_07 (14. Jun 2010)

fassy hat gesagt.:


> Ich würde eherlich gesagt beim insert von Tabelle1 in Tabelle2 die ID von 1 mit übernehmen. Entweder als eigene Spalte oder aber warum nicht direkt die ID von Tabelle2 überschreiben?


Überschreibe ich die ID in TABLE2, dann bekomm ich ein "datatype dismatch".
Füge ich die ID_Table1 in Table2 in eine neue Spalte (id_b) und versuche dann 
	
	
	
	





```
DELETE FROM Table1 WHERE id IN (SELECT id_b FROM TABLE2)
```
 läuft alles durch nur nicht der Löschvorgang.
Irgendwie klappt es nur wenn ich zwei PK Felder miteinander verifiziere.



fassy hat gesagt.:


> Ich versteh allerdings auch gar nicht was du genau vorhast. In Tabelle1 einfügen, dann nach Tabelle2 kopieren und in Tabelle1 wieder löschen. Das ist nicht grade ein robuster und guter Programmierstil.


 Table1 stellt eine aktuelle Tourübersicht dar, die sich aktualiesert, sobald eine neue Tour erfasst wird oder im TABLE1 gelöscht wird. Dies soll in einem JTable sichtbar werden. TABLE2 bildet die Abschlussübersicht, in der alle Touren am Ende zeitlich sortiert erfasst sind. TABLE1 dient als Zwischenspeicher. Eine andere Lösung viel mir nicht ein und mit meinen Kenntnissen der Programmierung bin ich schnell bis hierher gekommen:rtfm:.
Der Zwischenspeicher wird nie groß, da Touren zeitnah abgearbeitet werden. Anhand der Zeit und des Fahrzeugs kann ich die entsprechende Tour bestimmen - ID ist besser. Wie du schon sagtest:" das muss funktionieren." Ich habe die Tables auch schon komplett neu aufgebaut, ohne Erfolg.


----------



## Michael... (14. Jun 2010)

Chriss_07 hat gesagt.:


> Füge ich die ID_Table1 in Table2 in eine neue Spalte (id_b) und versuche dann
> 
> 
> 
> ...


Bedeutet das Du bekommst eine Fehlermeldung oder wird einfach nicht gelöscht?


Chriss_07 hat gesagt.:


> Table1 stellt eine aktuelle Tourübersicht dar, die sich aktualiesert, sobald eine neue Tour erfasst wird oder im TABLE1 gelöscht wird. Dies soll in einem JTable sichtbar werden. TABLE2 bildet die Abschlussübersicht, in der alle Touren am Ende zeitlich sortiert erfasst sind. TABLE1 dient als Zwischenspeicher.


Der Grund für die zweite Tabelle ist mir nicht klar. Du kannst doch alles in einer Tabelle halten und die JTable zeigt nur den gewünschten Ausschnitt aus der Tabelle an.


----------



## Chriss_07 (14. Jun 2010)

In dem Fall kommt KEINE Fehlermeldung und es wird NICHTS gelöscht. Fehlermeldung bekam ich nur, wenn die Columnsanzahl nicht stimmte oder der PK von TABLE2 überschrieben werden sollte.



Michael... hat gesagt.:


> Der Grund für die zweite Tabelle ist mir nicht klar. Du kannst doch alles in einer Tabelle halten und die JTable zeigt nur den gewünschten Ausschnitt aus der Tabelle an.


:bahnhof: WIE?? Gib mir einen Denkanstoss!!!


----------



## Michael... (14. Jun 2010)

Keine Ahnung was genau Du vorhast, oder wie Deine Tabelle aussieht, aber wenn Du z.B. eine Tabelle ala: TourID, EtappenID, Zeit, Startort, Zielort, ... hast und jetzt nur die Etappen einer konkreten Tour anzeigen und bearbeiten willst, kannst Du Dir ja per 
	
	
	
	





```
Select EtappenID, Zeit, Startort, Zielort From TourTable Where TourID = 2
```
 eben nur die für Tour 2 relevanten Infos auslesen, in der JTable anzeigen und bearbeiten.


----------



## Chriss_07 (14. Jun 2010)

:idea:
verstehe. Also in meinem fall müsste für alle angelegten Etappen eine ID (PK) hinterlegt werden und die TourID bleibt leer.


```
SELECT EtappenID, Zeit, Startort, Zielort FROM TourTable WHERE TourID = null
```
Wird eine Etappe(Tour) beendet, wird die Tour ID gefüllt und diese nicht mehr gelistet.
Das ganze noch 
	
	
	
	





```
ORDER BY zeit
```
, dann ist der zeitliche Ablauf wieder hergestellt.
Aber ich weiß das der Schreibvorgang scheiterte weil einmal fälschlicherweise , weniger Werte als Columns hinterlegen wollte. Das ist doch sicherlich nur ein SQL Kommando Problem?


----------



## Michael... (14. Jun 2010)

Chriss_07 hat gesagt.:


> verstehe. Also in meinem fall müsste für alle angelegten Etappen eine ID (PK) hinterlegt werden und die TourID bleibt leer.
> 
> 
> ```
> ...


Hört sich so machbar an


Chriss_07 hat gesagt.:


> Aber ich weiß das der Schreibvorgang scheiterte weil einmal fälschlicherweise , weniger Werte als Columns hinterlegen wollte. Das ist doch sicherlich nur ein SQL Kommando Problem?


Ist meistens der Fall ;-)


----------



## Chriss_07 (14. Jun 2010)

Brauch da noch mal ein Rat zum 
	
	
	
	





```
INSERT
```
Einige Werte sind bereits in der _ROW_ nun kommen weitere dazu

```
insert into tour (zielort, zielstrasse, kilometer)
```
 wo die 
	
	
	
	





```
ID = tour.getSplit()[3]
```
ist.
Das ist die ID, die ich mit dem String übergebe, um der ausgewählte Tour die letzten Werte zu kommen zu lassen.


----------



## Michael... (14. Jun 2010)

Chriss_07 hat gesagt.:


> Brauch da noch mal ein Rat zum
> 
> 
> 
> ...


Wenn ein Datensatz bereits existiert brauchst Du kein Insert sondern ein Update Statement

```
Update TourTable Set ziel = 'München' Where ID = 2
```


----------



## Chriss_07 (14. Jun 2010)

:bloed:
Danke, jetzt werden mir auch die richtigen Werte via 
	
	
	
	





```
get.Zielstrasse() usw...
```
 angezeigt. Auch die ID passt.
Nur es findet kein Updatevorgang statt:cry:

Ich habe insgesamt zwei Datenbanken mit jeweils zwei Tables und zu beiden verwende ich die selbe Klasse, ist das ok??

```
public class DBconnectdb {

	public static Connection conn;
	public static Connection con;

    
    public DBconnectdb() {    
    	
    }
```
Die Methoden stimmen ja soweit....


----------



## Chriss_07 (15. Jun 2010)

Das Problem scheint in der ID zu liegen, die ich mir aus dem String[] hole.


```
UPDATE tour SET ..... WHERE ID = ' 3'
```
 Es wird ein Leerzeichen mit übergeben, deshalb kann die richtige ID in der DB nicht gefunden werden. Ich habe die Query ohne Leerzeichen in der DB getestet und das funktioniert. 
Wie bekomme ich das Leerzeichen aus dem String?

```
public void setTour(Object tour) {
		this.tour = tour;
	
	split = ((String) tour).split(",");
	for(int i = 0, length = split.length;i < length; i++){
		System.out.println(split[i]);
		}
	}
	
	public void setSplit(String split[]){
		this.split = split;
	}
	public String[] getSplit(){
		return split;
	}
```


EDIT: Fehler gefunden. Den String gebe ich zuvor zur Auswahl in eine ComboBox via 
	
	
	
	





```
results4.add(tour1 + " , " + tour2 + " , " + tour3 + "," + tour4 );
```
 Die Lücken vor und nach einem Komma dienen der Übersichlichkeit aber fügen auch ein Leerzeichen ein. Nun rückt die ID zwar näher an das Komma aber sie kann in der DB der entsprechenden ID wieder zugeordnetz werden. 
UPDATE funktioniert.


----------



## Michael... (15. Jun 2010)

Von der Vorgehensweise ist das sicher noch optimierbar. Erst die ID zu einem String verketten um sie dann wieder per split zu trennen (wenn da immer ein Blank hinter dem Komma steht, hätte auch split(", ") funktioniert, oder um auf Nummer sicher zu gehen sowas wie split("\\s*,\\s*") verwenden)

Ansonsten würde ich - aus persönlicher Erfahrung - empfehlen PreparedStatements zu verwenden.


----------



## Gast2 (15. Jun 2010)

Chriss_07 hat gesagt.:


> Das Problem scheint in der ID zu liegen, die ich mir aus dem String[] hole.
> 
> 
> ```
> ...




```
String s = "   3 ";
System.out.println(s);
s = s.trim();
System.out.println(s);
```

Zum Rest... Versuch doch bitte mal nach Prepared Statements zu suchen hier im Forum. String konkatenieren zu einem SQL ist äußert schlechter Stil und zudem sehr fehleranfällig.

//EDIT - huch da war ja noch ien Kommentar auf der nächsten Seite


----------



## Chriss_07 (15. Jun 2010)

danke euch beiden, das mit dem 
	
	
	
	





```
split(", ")
```
 ist schonmal glasklar.

Damit die Datenbank aber nicht ins Unermessliche steigt, soll täglich ein Schlusstrich gezogen werden.
Aus betriebswirtschaftlichen Gründen kann man diese dann in ein XLS Format exportieren(POI/JExcel). Das sollte ja eine handliche Grundlage werden. Mit SQLLite DB kann man schlecht weiter arbeiten.
Das ist mit Sicherheit ein neuen Thread wert aber vllt habt ihr noch fix einen Denkanstoss für mich, wie ich diesen Table verwerte. Ich habe mir dazu schon den _Java Timer_ angesehen, bin mir aber nicht im Klaren, ob eine zeitgesteuerte Variante die Lösung ist.
Ein Problemfall könnte sein, dass kurz vor EXPORT eine offene Tour falsch verbucht wird oder gar nicht verbucht wird. Eine Methode zum Löschen der Datensätze hintenran, damit die IDs nicht nach einem Jahr in die tausende gehen. Das wird für mich (mit Hilfe von Java programmieren aus Leidenschaft ) schon machbar werden. 
Nur wie kann ich vom Grundgedanken her den _Timer _implementieren?
Hat da jemand eine Idee?


----------



## Gast2 (15. Jun 2010)

Was willst du genau? Zu einem bestimmten Zeitpunkt eine Tabelle als Excel Tabelle exportieren und dann dann wieder bei 0 anfangen? Das würde bedeuten du hast ein Serverprogramm, Webapp oder ähnliches das 24/7 läuft? Oder wie sieht deine Application aus?


----------



## Michael... (16. Jun 2010)

Wenn ich das richtig verstanden habe, willst Du in regelmässigen Abständen bzw. zu festen Zeitpunkten Datensätze aus der DB archivieren. Das wäre aber dann nicht Aufgabe Deiner Applikation sondern der Datenbank.
Ein Timer ist zwar etwas, das eine Aktion verzögert und/oder in regelmäßigen Abständen ausführt,  allerdings nur zur Laufzeit der Applikation.


----------



## Chriss_07 (16. Jun 2010)

Ja genau, als Webapplikation hatte ich es mir nicht gedacht, wäre aber auch ein schöner Gedanke.
Für die Firma meines Vaters wäre ein Abschluss um 18:00 Uhr ausreichend, um die Courierfahrten zu hinterlegen (kleiner Betrieb mit drei Fahrzeugen). Allerdings kommt es ab und an mal vor das eine Fahrt in der Nacht anfällt. Da der Rechner eh ununterbrochen läuft, dachte ich an eine automatischen Export um Mitternacht. 
Um nun mal alle plausiblen Möglichkeiten in Betracht zu ziehen, könnte auch eine Lieferung vor Mitternacht sein, die aber erst nach Mitternacht abgeschlossen wird ( Änderungen bzgl des Zielortes sind keine Unregelmäßigkeit). Dann sollte natürlich die Tour zum vorherigen Tag gebucht werden und nicht zum Neuen. Daher müsste ich nicht nur die Uhrzeit sondern auch das Datum berücksichtigen, richtig? Das XLS bzw. CSV sollte mit dem Datum benannt werden. Die Rows im TABLE müssten entfernt werden. Wie schaut es mit der ID aus, die ja immer weiter ansteigt? Könnte das nach drei vier JAhren zu einem Problem werden?
Wie könnte ich diesen Plan umsetzen( grobe Skizzierung - ich muss mich erstmal mit der Materie beschäftigen)?


----------

