# ORA-02291: integrity constraint.



## metaltiffy (25. Sep 2007)

Ich hab ein Problem...
Ich füge mit :
	
	
	
	





```
String insertc_t = "INSERT INTO C_T"
						+"(Song_id, CD_id)" 
						+"Values"
						+"('"+song_id+"'"
						+",'"+dat_id+"')";
					System.out.println(insertc_t);
					rs4 = st.executeQuery(insertc_t);
```
Daten in eine Tabelle ein, bzw. ich versuche es...
vorher füge ich in eine andere tabelle die song_id (Fremdschlüßel für die Song_id)
und er sagt das der schlüßel nciht passt...

Dabei passen beide überein...

das sind die beiden Zeilen und da sind beide gleich..


> INSERT INTO Song(Song_id, T_Titel, i_id)Values('205','test','2')
> INSERT INTO C_T(Song_id, CD_id)Values('205','94')



Mache ich das direkt in SQL funktioniert es..

Ich hab auch schon ein commit dazwischen gesetzt, falls die erste nicht sofort auf dem neuesten stand ist, und so der Schlüßel noch nicht da ist..
Nichts hilft..

Das ist die Funktion, in der der Kram gemacht wird..



```
public void speichern(){
		try {
			cn.setAutoCommit(true);
			if (file == null){
				labmeld.setText("kein Bild ausgewählt");
			}
			else {
		    st = cn.createStatement();
		    String herst = t_herst.getText();
		    int jahr = Integer.parseInt(t_jahr.getText());
		    double vork = Double.parseDouble(t_preis.getText());
		    // nächsten Seq-Wert kriegen
		    String str_seq = "select seq_dat.nextval FROM dual";
		    System.out.println(str_seq);
		    rs_id = st.executeQuery(str_seq);
		    rs_id.next();
			int dat_id = rs_id.getInt(1);	
			System.out.println("dat_id"+dat_id);
		    String str_insertdat = "INSERT INTO Datentraeger " 
		        + "(dat_id , Hersteller, Preis, E_Jahr,TYP_ID ) "
		        + "VALUES "
		        + "('" + dat_id  + "',"
		        + "'" + herst   + "',"
		        + vork + ","
		        + jahr + ","
		        + datdefi + ")";
		    System.out.println(str_insertdat);
		    st.executeQuery("Commit");
		    st.executeUpdate(str_insertdat); 
		    String titel = t_titel.getText();
		    String bildstatm = "";
		    switch (datdefi) {
		    case 1:// CD
				rs2 = st.executeQuery("INSERT INTO CD"
						+"(CD_id, CD_Titel)" 
						+"Values"
						+"('"+dat_id+"'"
						+",'"+titel+"')");		
				
				for (int i = 0; i < Max;i++){
					String seq_Song = "select seq_Song.nextval FROM dual";
				    rs_id = st.executeQuery(seq_Song);
				    rs_id.next();
				    int song_id = rs_id.getInt(1);
				    st.executeQuery("Commit");
				    String insertsong = "INSERT INTO Song"
						+"(Song_id, T_Titel, i_id)" 
						+"Values"
						+"('"+song_id+"'"
						+",'"+song[i]+"'"
						+",'"+i_id[i]+"')";
				    System.out.println(insertsong);
					rs3 = st.executeQuery(insertsong);
					st.executeQuery("Commit");
					String insertc_t = "INSERT INTO C_T"
						+"(Song_id, CD_id)" 
						+"Values"
						+"('"+song_id+"'"
						+",'"+dat_id+"')";
					System.out.println(insertc_t);
					rs4 = st.executeQuery(insertc_t);
				}
				System.out.println("in c_T");
				bildstatm = ("update CD set CD_BILD = ? where CD_id  ='"+dat_id +"'");
				break;
			case 2:// DVD
				
				break;
			case 3:// Software
				
				break;
			default:
				labmeld.setText("kein Datentraegertyp markiert");
		    }
		    System.out.println(bildstatm);
		    fis     = new FileInputStream(file);
		    pst = cn.prepareStatement(bildstatm);
		    pst.setBinaryStream( 1, fis, (int)file.length() );  
		    pst.executeUpdate();
		    System.out.println( file.length() + " Bytes successfully loaded." );
		    st.executeQuery("Commit");
			}
		} catch (Exception ex) {
			System.out.println(ex);
			ex.printStackTrace();
		} finally {
			try {
				if (null != fis) fis.close(); } catch (Exception ex) {
			}
			try {
				if (null != pst)	pst.close();	} catch (Exception ex) {
			}
		}// ende finally
	}
```


----------



## SlaterB (25. Sep 2007)

> Mache ich das direkt in SQL funktioniert es.. 
+ 
> Das ist die Funktion, in der der Kram gemacht wird.. 

->
die Java-Operation sollte bis auf try/ catch nur aus höchstens 10 Zeilen bestehen,
createStatement, die beiden festen fertigen Test-Insert-Strings (ohne jede Art von Variablen, switch oder ähnlichen Unfug) executen und fertig,
funktioniert das ja oder nein?, alles andere ist (zunächst) irrelevant,
mit Autocommit natürlich noch bisschen testen


funktioniert es, erst ein Insert durchzuführen und 5 Min. später in einem anderen Programm das zweite?
ist es also ein Problem der direkten Hintereinanderausführung oder ein generelles Einfügeproblem?


----------



## metaltiffy (25. Sep 2007)

autocommit hab ich ja schon auf true...
 wenn ich den switchkram und die variablen und so entferne geht es...


```
public void speichern(){
		try {
			cn.setAutoCommit(true);
//			if (file == null){
//				labmeld.setText("kein Bild ausgewählt");
//			}
//			else {
		    st = cn.createStatement();
		    String herst = t_herst.getText();
		    int jahr = Integer.parseInt(t_jahr.getText());
		    double vork = Double.parseDouble(t_preis.getText());
		    // nächsten Seq-Wert kriegen
		    String str_seq = "select seq_dat.nextval FROM dual";
		    System.out.println(str_seq);
		    rs_id = st.executeQuery(str_seq);
		    rs_id.next();
			int dat_id = rs_id.getInt(1);	
			System.out.println("dat_id"+dat_id);
		    String str_insertdat = "INSERT INTO Datentraeger " 
		        + "(dat_id , Hersteller, Preis, E_Jahr,TYP_ID ) "
		        + "VALUES "
		        + "('" + dat_id  + "',"
		        + "'" + herst   + "',"
		        + vork + ","
		        + jahr + ","
		        + datdefi + ")";
		    System.out.println(str_insertdat);
		    st.executeQuery("Commit");
		    st.executeUpdate(str_insertdat); 
		    String titel = t_titel.getText();
		    String bildstatm = "";
		    switch (datdefi) {
		    case 1:// CD
				rs2 = st.executeQuery("INSERT INTO CD"
						+"(CD_id, CD_Titel)" 
						+"Values"
						+"('"+dat_id+"'"
						+",'"+titel+"')");		
				st.execute("INSERT INTO Song(Song_id, T_Titel, i_id)Values(207,'test1',2)");
				st.execute("Commit");
				st.execute("INSERT INTO C_T(Song_id, CD_id)Values(207,95)");
				}
				System.out.println("in c_T");
				bildstatm = ("update CD set CD_BILD = ? where CD_id  ='"+dat_id +"'");
				break;
				break;
			default:
				labmeld.setText("kein Datentraegertyp markiert");
		    }
		    System.out.println(bildstatm);
		    fis     = new FileInputStream(file);
		    pst = cn.prepareStatement(bildstatm);
		    pst.setBinaryStream( 1, fis, (int)file.length() );  
		    pst.executeUpdate();
		    System.out.println( file.length() + " Bytes successfully loaded." );
		    st.executeQuery("Commit");
//			}
		} catch (Exception ex) {
			System.out.println(ex);
			ex.printStackTrace();
		} finally {
			try {
				if (null != fis) fis.close(); } catch (Exception ex) {
			}
			try {
				if (null != pst)	pst.close();	} catch (Exception ex) {
			}
		}// ende finally
	}
```


Aber irgendeinen Grund muss es ja haben, das es so kurz geht und lang nicht....
*verzweifel..*
ohne variablen und den kram, bringt mir das nichts...


----------



## SlaterB (25. Sep 2007)

wo hast du da ein switch entfernt, fehlt nicht einfach nur die for-Schleife Zeile 40 bis 62 im vorherigen Code?

wie auch immer, wenn es nun funktioniert kannst du ja kaum noch über Oracle meckern,
aber durch deinen Code durchzusehen dürfte schwer von jemand anderem zu erwarten sein,
wenn du da noch weitergehende Fragen hast musst du wohl sehr sehr viel erklären


----------



## metaltiffy (25. Sep 2007)

Ich entferne ja ncihts, was ich später noch brauche...
aber so funktioniert es jedenfalls...

Was soll ich denn erklären??
Über ein Frontend werden die daten eingegeben...
in der switch ist die wahl zwischen einem datensatz einer DVD, einer CD, und einem Spiel...
Der DVD und Spiel-kram funktioniert, aber die CD-SAche halt nicht...

muss in 4 tabellen etwas reingeschrieben werden..

CD<-->>C_T<<-->Song<<-->Interpret
So sieht der Aufbau aus...
zuerst wird in Interpret, dann in CD dann in Song und letztlich soll in C_T geschrieben werden, was aber Probleme mit dem Fremdschlüßel von Song hat...

----
Hoffe das is genug erklärt.....


----------



## SlaterB (25. Sep 2007)

das wichtigste hast du nicht mal angerissen: besteht noch eine Frage?

> aber so funktioniert es jedenfalls... 

klingt ja recht befriedigend

-----
> Hoffe das is genug erklärt.....

was dein Programm macht ist egal,
wichtig ist, welche SQL-Befehle du da durchführst bei deinem Problem (so denn überhaupt eins besteht)

um sowas zu verstehen sind Schleifen, switches usw Gift,
wie gesagt, ein ganz einfaches Programm:
Statement s = createStatement();
s.execute("Insert XY"); // ohne Variablen oder irgendwelchen Quatsch;
s.execute("Insert YZ");

3 Zeilen und fertig, geht oder geht nicht, mehr kann dazu ja gar nicht sagen,

wenn du dagegen

```
String str_insertdat = "INSERT INTO Datentraeger " 
              + "(dat_id , Hersteller, Preis, E_Jahr,TYP_ID ) " 
              + "VALUES " 
              + "('" + dat_id  + "'," 
              + "'" + herst   + "'," 
              + vork + "," 
              + jahr + "," 
              + datdefi + ")";
```
benutzt ist jede Hilfe verloren, wer soll schon überblicken, was in jeder einzelnen Variable drinsteht,
welche switch-case durchlaufen werden usw usf.

-----------

> Ich entferne ja ncihts, was ich später noch brauche... 

doch nur zum TESTEN bei diesem aktuellen Problem,
wenn du keine CD speichern kannst, wozu musst du dann komplizierte 20 Zeilen zur Bestimmung des Jahres in deinen Code drin haben, die 30 undurchsichtige Querfehler verursachen können,
wirf überall jahr raus und schreibe 2007,
schon ist dein Code lesbar und das Problem greifbarer,
im Idealfall tritt das Problem gar nicht mehr auf, und du hast einen Hinweis, woran es gelegen hat,

natürlich später wieder den alten Code einfügen


----------



## metaltiffy (25. Sep 2007)

Hab im Beitrag davor ja geschrieben, das es geht, mir ohne variablen aber nichts nützt
das soollte es einfügen

Insert in Interpret: I_id = 2
INSERT INTO Datentraeger (dat_id , Hersteller, Preis, E_Jahr,TYP_ID ) VALUES ('98','Test',19.99,2007,1)
INSERT INTO Song(Song_id, T_Titel, i_id)Values(211,'test',2)
INSERT INTO C_T(Song_id, CD_id)Values(211,98)

hab das jetzt mal mit beispielwerten gefüllt... sonst stehen da die variablen, die aber die gleichen werte enthalten wie in dem beispiel,
füge ich das mit den vorgegebenen Werten ein, geht es.
Mache ich das ganze mit variablen, kommt ein fehler raus


----------



## ms (25. Sep 2007)

Dann wirds wohl an dem Inhalt der Variablen liegen.
Gib doch mal die erzeugten Statements an der Console aus poste sie hier.

ms


----------



## metaltiffy (25. Sep 2007)

Sorry das es so lange gedauert hat, aber das Programm hatte sich aufgehangen nach meinen neuen Veränderungen und wollte nichts ausspucken ...

DAs sind die Statements

INSERT INTO Datentraeger (dat_id , Hersteller, Preis, E_Jahr,TYP_ID ) VALUES ('106','Test',19.99,2007,1)
INSERT INTO Song(Song_id, T_Titel, i_id)Values(217,'test',2)
INSERT INTO C_T(Song_id, CD_id)Values(217,106)

von C_T die Song_id hat ein constraint auf die Song_id von Song..
Wie man sieht sind beide 217..
also müßte es eigentlich laufen...


----------



## growler (25. Sep 2007)

stmt.executeUpdate ("INSERT INTO blatt () VALUES ('"+variable+"');");
also mit der syntax tut des bei mir einwandfrei... 
vergleichs mal bitte mit deiner

MFG
growler


----------



## metaltiffy (25. Sep 2007)

("INSERT INTO C_T"
						+"(Song_id, CD_id)" 
						+"Values"
						+"("+song_id
						+","+dat_id+")");

So siehts bei mir aus...
is ja das gleiche nur vertikal angeordnet....
Und das Semikolon hab ich nicht, weil das bei mir nicht läuft...
Aber das wird ja auch ne andere Fehlermeldung geben..


----------



## growler (25. Sep 2007)

("INSERT INTO C_T" 
+"(Song_id, CD_id)" 
+"Values" 
+"('"+song_id+"','"+dat_id+"');"); 

probiers mal so


----------



## metaltiffy (25. Sep 2007)

erstmal kam der Fehler ORA-00911: invalid character

nach entfernen des Semikolons wieder der gleiche
ORA-02291: integrity constraint (SCWEP01.SYS_C0031151) violated - parent key not found

Schade, aber danke für den Versuch
------------------EDIT
kann es daran liegen, dass ich immer st als Statement nehme, obwohl ich soviele Sachen aufrufe
oder is es besser für jedes ein eigenes z.b. st1, st2....


----------



## SlaterB (25. Sep 2007)

> kann es daran liegen, dass ich immer st als Statement nehme, obwohl ich soviele Sachen aufrufe 
oder is es besser für jedes ein eigenes z.b. st1, st2....

diese Frage verbietet sich, denn du hast doch ein funktionierendes Beispiel als Vorlage,
wenn du für die Variablen-Variante ein anderes System benutzt (andere Menge an Statements, Commits, Einfügereihenfolge..)
dann weißt du, woran du arbeiten musst


----------



## metaltiffy (25. Sep 2007)

Hmm... darüber hab ich garnicht nachgedacht.. in dem funktionierenden, hab ich das genauso.. alles mit einem Statement...
Noch eine Sache die man ausschließen kann..
Ich krieg gleich nen Nervenzusammenbruch...


----------



## metaltiffy (25. Sep 2007)

Argh!!

Hat sich erledigt...
Hatte nen Trigger auf Song..
deswegen hat der wohl die von mir übergebene Song_id nicht genommen und seine genommen...
deswegen konnte das nciht übereinstimmen...
Habs gemerkt, weil bei den Songs die ich angelegt hatte, die id immer um 2 größer wurde, statt um eins...

Sorry für die Umstände..


----------

