Zum Inhalt springen

Oracle Abfragen mit DBAL und execute_SELECTquery aus eigener Extension

Erstellt am 22. April 2009 · 2 Antworten · letzte Antwort am 9. Mai 2009

Tags: Datenbank, Frage

Tarta ·

Hallo zusammen,

ich habe leider mal wieder ein Problem, dass ich trotz stundenlanger Suche bisher nicht lösen kann. Ich stehe vor der Aufgabe eine Extension zu schreiben, aus der eine (oder mehrere) Tabellen aus einer Oracle-Datenbank abgefragt werden. Die Typo3-Umgebung läuft dabei weiterhin unter MySQL. Nutzen möchte ich die Funktionen der DBAL-Extension um sauber zu bleiben und die Erweiterbarkeit zu gewährleisten.

Folgendes habe ich gemacht:
- AdoDB installiert
- DBAL installiert

Folgenden Code in die localconf.php eingefügt:

$TYPO3_CONF_VARS['EXTCONF']['dbal']['handlerCfg'] = array (
	'_DEFAULT' => array (
		'type' => 'native',
		'config' => array(
			'username' => '', // Set by default (overridden)
			'password' => '', // Set by default (overridden)
			'host' => '', // Set by default (overridden)
			'database' => '', // Set by default (overridden)
		)
	),
	'oracleDB' => array (
		'type' => 'adodb',
		'config' => array(
			'username' => 'geheimerusername',
			'password' => 'geheimespasswort',
			'host' => '192.168.30.127',
			'database' => 'report',
			'driver' => 'oci8'
		)
	),
);
$TYPO3_CONF_VARS['EXTCONF']['dbal']['table2handlerKeys'] = array(
	'test_intranet' => 'oracleDB',
);

$TYPO3_CONF_VARS['EXTCONF']['dbal']['debugOptions']     = array(

        'enabled' => TRUE,        // Generally, enable debugging.
        'printErrors' => TRUE,    // Enable output of SQL errors after query executions.
        'EXPLAIN' => 1,           // EXPLAIN SELECT ...(Only on default handler)
        'parseQuery' => 1,        // Parsing queries, testing parsability (All queries)
        'joinTables' => 1
    );

Zugegriffen werden soll auf die Tabelle test_intranet der Datenbank report.

Folgenden Quelltext habe ich nun in der Extension verwendet:

	function main($content, $conf) {
		$this->conf = $conf;
		$this->pi_setPiVarDefaults();
		$this->pi_loadLL();
		$this->pi_USER_INT_obj = 1;	// Configuring so caching is not expected. This value means that no cHash params are ever set. We do this, because it's a USER_INT object!

		$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
				'*',
				'test_intranet',
				'',
				'',
				'',
				''
		);
	
		
		while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
			$content .= $row['username'];
		}

		return $content;
	}

Leider bekomme ich im Debug-Bereich des DBAL die Meldung "ORA-00942: table or view does not exist". Die Tabelle existiert aber, und mit folgendem Code kann ich (ohne Typo3) darauf zugreifen:

		//oracle connection variables
		$ora_user = 'geheimerusername';    //username
		$ora_pass = 'geheimespasswort';            //user password
		$ora_host = '192.168.30.127';        //host name or server ip address
		$ora_db   = 'report';    //database name

		// place variable into oci_connect function, then place funtion in variable
		$ora_conn = oci_connect($ora_user,$ora_pass,'//'.$ora_host.'/'.$ora_db);

		// error handling
		if (!ora_conn){                            // if variable $ora_conn fails to connect
			// do the following if it fails
			$ora_conn_erno = oci_error();             // insert oci_error() function into variable
			$content .= ($ora_conn_erno['message']."\n");     // print the $ora_conn_erno variable/oci_error() function selecting only the message (human readable)
			oci_close($ora_conn);                     // close the connection just in case php doesn't close it
		} else {
			// if it doesn't fail it will proceed with the rest of the script
			$content .= "Connection Succesful\n";     //echo message if connection does not error
			           // close the connection
		}
		
		$query = 'SELECT HANDELSBUCHNUMMER, BEZEICHNUNG FROM test_intranet WHERE rownum <20';
		
		$stid = oci_parse($ora_conn, $query);
		if (!$stid) {
			$e = oci_error($ora_conn);
			$content .= htmlentities($e['message']);
		}
		
		$r = oci_execute($stid, OCI_DEFAULT);
		if (!$r) {
			$e = oci_error($stid);
			$content .= htmlentities($e['message']);			
		}
		
		$content .= "<table border="1">";
		while($row=oci_fetch_array($stid, OCI_RETURN_NULLS)) {
			$content .= '<tr>';
				foreach ($row as $item) {
					$content .= '<td>'.($item).'</td>';					
				}
				$content .= '</tr>';
		}
		$content .= '</table>';
				
		
		oci_close($ora_conn);

Meine Frage nun: Muss ich noch irgendwo die Datenbankverbindung aufbauen? Oder wird das mit der vorliegenden Konfiguration schon erledigt? Bin ein wenig ratlos wo ich noch suchen soll!

Vielen Dank schonmal.

Tarta

Tarta ·

Hey,

da ich leider nirgendwo eine Lösung für dieses Problem gefunden habe, das DBAL aber eigentlich auch nicht benötige, da die Extension nur für einen internen und sehr spezifischen Anwendungsfall benötigt wird, stelle ich den Datenbankzugriff nun direkt aus der Extension her:

Funktionen:

function oracleConnect() {
  $this->oc = oci_connect($this->conf["oracleUser"],$this->conf["oraclePassword"],'//'.$this->conf["oracleServer"].'/'.$this->conf["oracleDatabase"]);

  if (!$this->oc) {
    $ora_conn_erno = oci_error();             
    $content .= ($ora_conn_erno['message']."\n");     
    oci_close($this->oc);                     
    return $content;
  } else {
    $content .= "Connection Succesful\n";     
    return true;
  }

}

function oracleDisconnect() {
  if (is_resource($this->oc)) {
    oci_close($this->oc);
  } else {
    $error = "<p class='fatal_error'>Datenbankverbindung kann nicht geschlossen werden, da nicht existent.</p>";
    return $error;
  }
}

function oracleQuery($query) {

  $stid = oci_parse($this->oc, $query);
  if (!$stid) {
    $e = oci_error($ora_conn);
    $content .= htmlentities($e['message']);
  }

  $r = oci_execute($stid, OCI_DEFAULT);
  if (!$r) {
    $e = oci_error($stid);
    $content .= htmlentities($e['message']);
  }

  return $stid;

}

und Code zum aufrufen:

$sql = "SELECT * FROM test";

$dbConnection = $this->oracleConnect();
if ($dbConnection === TRUE) {

  $stid = $this->oracleQuery($sql);
  $count = 0;
  while($row = oci_fetch_assoc($stid)) {
    $resArray[$count] = $row;
    $count++;
  }
}

echo "<pre>";
print_r($resArray);
echo "</pre>";

Viele Grüße

Tarta

Tomsel ·

Hallo Tatra,

um in Typo3 Oracle-Tabellen ansprechen zu können,
solltest du mal versuchen mal alle Tabellenamen und Feldnamen
in Uppercase anzusprechen.. 😉

LG