# Java + sql - query kürzen?



## Blame23 (5. Dezember 2007)

Hi,

ich hab ein kleines java tool geschrieben dass eine query von einer textdatei in eine String variable einliest und dann auf der datenbank ausführt.
Die query ist sehr lang, steht aber nur in einer Zeile (sodass ich nur eine zeile einlesen muss).

Dass komische ist nun dass wenn ich die query in den java code schreibe. also 

```
String query1 = "SELECT bla von bla...";
```
 dann funktioniert es. Aber wenn ich diese Zeile aus einer Textdatei einlese und ausführen möchte kommt:

```
Bezeichner (beginnend mit 'SELECT CAST(SO.[name] AS CHAR(20)) AS TableName, CAST(SI.[name] AS CHAR(30)) AS IndexName, CAST(SC.[name] AS CHAR(15)) AS ColNam') ist zu lang. Die Maximallõnge betrõgt 128.
```

Ich denke mal die Lösung wäre ein Zeilenumbruch nach 128 Zeichen. Aber wie geht dass wenn der String ja in einer Variablen "query" steht.
Villeicht kennt ja jemand noch eine andere Lösung?

Bin für jede Hilfe dankbar!

Gruß
Blame


----------



## Matze (5. Dezember 2007)

Ich glaube das Problem liegt daran, dass du in deiner Textdatei " verwendest. Dies würde dann deinen String in Java unterbrechen. Damit du ein Anführungszeichen als String-Zeichen verwenden kannst musst du \" schreiben


----------



## Blame23 (5. Dezember 2007)

Hat leider nicht funktioniert. Hier mal die Query aus der Textdatei:

```
Query1="SELECT CAST(SO.[name] AS CHAR(20)) AS TableName, CAST(SI.[name] AS CHAR(30)) AS IndexName, CAST(SC.[name] AS CHAR(15)) AS ColName, CAST(ST.[name] AS CHAR(10)) AS TypeVal FROM SYSOBJECTS SO INNER JOIN SYSINDEXES SI INNER JOIN SYSINDEXKEYS SIK ON SIK.[id] = SI.[id]  AND SIK.indid = SI.indid INNER JOIN SYSCOLUMNS SC INNER JOIN  SYSTYPES ST ON SC.xtype = ST.xtype ON SIK.[id] = SC.[id]  AND SIK.colid = SC.colid ON SO.[id] = SI.[id] WHERE SO.xtype = 'u' AND SI.indid > 0 AND SI.indid < 255 AND (SI.status & 64)=0 ORDER BY TableName"
```
Der String wird nach dem "=" eingelesen.


----------



## Matze (5. Dezember 2007)

Ich weiß nicht ob du verstanden hast, was ich gemeint hab.

In der Konsole würde es zu Beispiel so lauten:

```
SELECT * FROM Beispieldatenbank WEHRE Name = "Mustermann";
```

Wenn du das jetzt Haargenau in Java kopieren würdest, würde es nicht funktioneren es müssten dann heißen:

```
....executeQuery("SELECT * FROM Beispieldatenbank WEHRE Name = \"Mustermann\";" );
```

Weißst du was ich meine? Das Problem ist, dass in Java immer wenn du " schreibst, ein Text anfängt oder aufhöhrt. In diesem Fall allerdings brauchst du ein " als Zeichen.


----------



## matdacat (5. Dezember 2007)

Poste mal den Code, wie Du die Textdatei ausliest. Bzw. lass Dir selbst mal den ausgelesenen String ausgeben.


----------



## Blame23 (5. Dezember 2007)

Also wenn ich mir den String mit System.out.println ausgebe wird er ganz angezeigt.

Hier meine main klasse:

```
public class CCsqlexec extends Object
{
	
 public static void main(String[] args) 
 { 

      	 SqlExec mssql = new SqlExec();
      	 OracleExec oracle = new OracleExec();
      	 
      	 //Parameter einlesen
      	 readIni ri = new readIni();
      	 ri.getParam();
      	 
      	 //Die richtige Methode für den Datenbanktyp auswählen
      	 if(ri.dbtype.equals("SQL2000")){mssql.SQL2000();}
      	 if(ri.dbtype.equals("SQL2005")){mssql.SQL2000();}
      	 if(ri.dbtype.equals("ORACLE")){oracle.SQLexecute();}
}
}
```

Die Klasse die die .ini einliest:


```
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class readIni{
String ip,port,dbname,user,pass,query1,query2,dbtype,line;
public void getParam()
 {

	 BufferedReader f;
	 try{
		 f = new BufferedReader(
			 new FileReader("CCsqlexec.ini"));
		 
		 while((line = f.readLine())!=null){
			 
			 if(line.startsWith("#")==false)
			 {
				
				 if(line.startsWith("IP")){ip=line.substring(3);}
				 if(line.startsWith("Port")){port=line.substring(5);}
				 if(line.startsWith("DatabaseName")){dbname=line.substring(13);}
				 if(line.startsWith("UserName")){user=line.substring(9);}
				 if(line.startsWith("Pass")){pass=line.substring(5);}
				 if(line.startsWith("Query1")){query1=line.substring(7);}
				 if(line.startsWith("Query2")){query2=line.substring(7);}
				 if(line.startsWith("DatabaseType")){dbtype=line.substring(13);}
			 }
			 
		 }
		 f.close();
	 }catch (IOException e){
		 System.out.println("Fehler beim Lesen der Datei CCsqlexec.ini");
		 System.out.println("Die Datei muss im selben Verzeichnis liegen!");
	 }
	 
 } 
 }
```

und die Klasse die den sql befehl ausführen soll:

```
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.sql.*;

/**
 *
 *Baut die Verbindung zu MS SQL2000 oder SQL2005 Datenbank auf und
 *führt max 2 queries aus.
 */

public class SqlExec extends Object {

		Connection connection = null;
	 	ResultSet resultSet = null;
	 	ResultSet resultSet2 = null;
	 	Statement statement = null;
	 	FileOutputStream out;
	    PrintStream p;
     	readIni ri = new readIni();


        public void SQL2000(){
        	//lese Parameter
        	ri.getParam();

        	//SQL2000 spezifischer Verbindungsaufbau
        	try{
			Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
	         String url = ("jdbc:microsoft:sqlserver://"+ri.ip+":"+ri.port+";DatabaseName="+ri.dbname+";User="+ri.user+";Password="+ri.pass);

	         //Verbindung aufbauen
	         connection = DriverManager.getConnection(url);
	         System.out.println("connected.\n executing query \n... please wait\n ");
	         SQLexecute();
        	}
         	catch (Exception e)
				{
   					e.printStackTrace();
				}
        }

        public void SQL2005(){
        	//lese Parameter
        	ri.getParam();
        	//SQL2005 spezifischer Verbindungsaufbau
        	try{
        	Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
	         String url =("jdbc:microsoft:sqlserver://"+ri.ip+":"+ri.port+";DatabaseName="+ri.dbname+";user="+ri.user+";password="+ri.pass);
	         System.out.println("connected.\n executing query \n... please wait\n ");
	         //Verbindung aufbauen
	         connection = DriverManager.getConnection(url);
	         SQLexecute();
        	}
         	catch (Exception e)
				{
   					e.printStackTrace();
				}
        }


	    public void SQLexecute(){

	    if((ri.query2) != null){
	    if(ri.query2 != ""){

		try{

	         statement = connection.createStatement();

	         //start query1
	         //Tabelle in Datei schreiben
	         out = new FileOutputStream("query1.csv");
	         p = new PrintStream( out );


			 System.out.println(ri.query1);
	         resultSet = statement.executeQuery(ri.query1);

	         //Überschriften (noch nicht getestet)
	         ResultSetMetaData meta = resultSet.getMetaData();
	         int columns = meta.getColumnCount();
	         int numerics = 0;

	         for ( int i = 1; i <= columns; i++ )
	         {
	        	 p.printf( meta.getColumnLabel(i));
	           //meta.getColumnTypeName(i)
	           if ( meta.isSigned(i) )
	             numerics++;
	         }


	         //p.printf( "%s; %s; %s; %s%n" , "TabellenName", "IndexName", "SpaltenName", "Typ");
	         while ( resultSet.next() ) {

	         //In Console anzeigen
	  		 //System.out.printf("%s, %s, %s, %s%n", resultSet.getString(1),
	         //resultSet.getString(2), resultSet.getString(3),resultSet.getString(4));

	         p.printf("%s; %s; %s; %s%n", resultSet.getString(1), resultSet.getString(2), resultSet.getString(3),resultSet.getString(4));
	                    				}
	         p.close();

	         //Zu testzwecken. falls die verbindung beendet wurde öffne sie erneut
	         if(connection.isClosed()){statement = connection.createStatement();}

	         //start query2
	         out = new FileOutputStream("query2.csv");
	         p = new PrintStream( out );
	         resultSet2 = statement.executeQuery(ri.query2);

	        // p.printf( "%s; %s; %s%n" , "TabellenName", "ConstraintName", "ColumnName");

	         while ( resultSet2.next() ) {
	         p.printf("%s, %s, %s%n", resultSet.getString(1), resultSet.getString(2), resultSet.getString(3));
	                  				}
	             p.close();
	          //ende query2
	         System.out.println("done. ");
	         System.out.println("press any key to exit");

	         	}
	         	catch (Exception e)
					{
	   					e.printStackTrace();
					}
	    }//end if1
	    }//end if2
      		}
	}
```

Ich weiß, alles eher quick & dirty aber soll auch nich mehr machen wie dieses query auszuführen.
Also das query geht auf jedenfall, wenn ich das auf dem SQLServer ausführe gehts auch.
Liegt das vill an dem M$ sql Treiber?

Gruß
Blame


Edit: Habe gerade gesehen dass jemand HIER das gleich Problem hatte und es durch Escapen des Strings gelöst hat.  
Die Methode dazu ist aber leider in C#, sollte aber eig. zu portieren sein.


----------



## Chefkoch333 (5. Dezember 2007)

Das ganze ist wirklich ein wenig dirty... 
Kannst du deine Ini Datei noch schicken?
Einen Tipp noch, schau dir mal java.util.Properties an. Diese Klasse macht das gleiche wie deine readIni Klasse. Nur ist sie nicht so Fehleranfällig (IndexOutOfBoundsException).


----------



## Chefkoch333 (5. Dezember 2007)

INI:

```
Query1="SELECT CAST...;"
```

versuch doch mal in der INI die Gänsefüsse wegzulassen, also so:

```
Query1=SELECT CAST...;
```

Du liest ja alles nach dem = aus und schreibst es in ri.query1. Danach gehst du damit direkt auf die Datenbank. Das bedeutet das die Gänsefüschen Teil des ausgeführten SQL Statements sind, welches das DBMS dann nicht versteht.


----------



## Blame23 (5. Dezember 2007)

Oh Mann.... 

Es lag wirklich an den Anführungszeichen... 
Vorher hatte ich den query im Java Source direkt drin als String also

```
String query="SELECT USW";
```

und irgendwie hatte ich dann die "" im Hinterkopf als ich die .ini Datei angelegt habe *g*

Naja auf jedenfall vielen Dank für die Hilfe!
Und ja... wenn das tool noch größer wird mach ich das auf jedenfall mit Properties.

Gruß
Blame


----------

