class DB_Sql {
var $Debug = false;
var $Home = "/u01/app/oracle/product/8.0.4";
var $Remote = 1;
/* このクエリは最初の接続の直後に送信されます。
例:
var $ConnectQuery="ALTER SESSION SET nls_date_ language=german nls_date_format='DD.MM.RRRR'";
->このセッションの日付形式を設定します。ora ロール
を変更できない場合はこれで問題ありません */
var $ConnectQuery='';
/* Oracle 8.0.5、Apache、および PHP3.0.6 での奇妙なエラーのため
ENV を設定する必要はありません - 私のシステムでは Apache
設定しないとゾンビに変わりますこれを FALSE に設定しないでください。
代わりに、Apache の起動前にこれらの ENV 変数を設定しました。
不明な場合は、うまくいくかどうか試してみてください。 */
var $OraPutEnv = true;
var $Database = "";
var $User = "";
var $Password = "";
var $Link_ID = 0;
var $Query_ID = 0;
var $Record = array();
var $Row;
var $Errno = 0;
var $Error = "";
var $ora_no_next_fetch=false;
/* 完全を期すために db_mysql からコピー */
/* public: 識別定数。これを決して変更しないでください。 */
var $type = "オラクル";
var $revision = "リビジョン: 1.3";
var $Halt_On_Error = "はい"; ## "yes" (メッセージを表示して停止)、"no" (エラーを静かに無視)、"report" (エラーを無視しますが、警告を吐き出します)
/* public:constructor */
function DB_Sql ($query = "") {
$this->query($query);
}
/* public: いくつかの簡単なレポート */
function link_id() {
return $this->Link_ID;
}
function query_id() {
return $this->Query_ID;
}
function connect() {
## これを行う理由は上記を参照してください
if ($this->OraPutEnv) {
PutEnv("ORACLE_SID=$this- >データベース");
PutEnv("ORACLE_HOME=$this->Home");
}
if ( 0 == $this->Link_ID ) {
if($this->Debug) {
printf("
$this に Connect() します->データベース...
n");
}
if($this->Remote) {
if($this->Debug) {
printf("
connect() $this->User/ ******@$this->データベース
n");
}
$this->Link_ID=ora_plogon
("$this->User/$this->; Password@$this->Database","");
/************** (SSilk によるコメント)
これは私のシステムでは機能しません:
$this->Link_ID=ora_plogon
("$this->ユーザー@$this->Database.world","$this->パスワード"); **********/
} else {
if($this->Debug) {
printf("
connect() $this->User, $this-> ;パスワード
n");
}
$this->Link_ID=ora_plogon("$this->ユーザー","$this->パスワード");
/* (SSilk によるコメント: これがどのように機能するかわかりませんが、このままにしておきます!) */
}
if($this->Debug) {
printf("
connect() Link_ID: $this->Link_ID
n");
}
if (!$this->Link_ID) {
$this->halt("connect() Link-ID == false " .
"($this->Link_ID), ora_plogon failed");
} else {
//echo "commit on
";
ora_commiton ($this->Link_ID);
}
if($this->Debug) {
printf("
connect() Link_ID を取得しました: $this->Link_IDn");
}
## 接続クエリを実行
if ($this->ConnectQuery) {
$this->query($this->ConnectQuery);
}
}
}
## システム/ユーザーごとのカーソルの数を増やすには、
## init.ora ファイルを編集して max_open_cursors パラメータを増やします。あなたのものは
## のデフォルト値で、ユーザーごとに 100 です。
## 私たちは、カーソルを保護するために
## を試みるという方法で query() の動作を変更しようとしましたが、その一方で、これには注意してください。
## は行わないでください。古い結果は使用しないでください。
##
## ->disconnect() を広範囲に使用することもできます。
## 未使用の QueryID は時々リサイクルされます。
function query($Query_String)
{
/* 空のクエリは使用しないでください。 */
if (empty($Query_String))
{
return 0;
}
$this->connect();
$this->lastQuery=$Query_String;
if (!$this->Query_ID) {
$this->Query_ID= ora_open($this->Link_ID);
}
if($this->Debug) {
printf("デバッグ: クエリ = %s
n", $Query_String);
printf("
デバッグ: クエリ ID: %d
n", $this->Query_ID);
}
if(!@ora_parse($this->Query_ID,$Query_String)) {
$this->Errno=ora_errorcode($this->Query_ID);
$this->Error=ora_error($this->Query_ID);
$this->halt("
ora_parse() が失敗しました:
$Query_String
これをスナップして sqlplus に貼り付けます!");
} elseif (!@ora_exec($this->Query_ID)) {
$this->Errno=ora_errorcode($this->Query_ID);
$this->Error=ora_error($this->Query_ID);
$this->halt("
n$Query_Stringn
これをスナップして sqlplus に貼り付けます!");
}
$this->Row=0;
if(!$this->Query_ID) {
$this->halt("無効な SQL: ".$Query_String);
}
return $this->Query_ID;
}
function next_record() {
if (!$this->gt;ora_no_next_fetch &&
0 == ora_fetch($this->Query_ID)) {
if ( $this->Debug) {
printf("
next_record(): ID: %d 行: %d
n",
$this->Query_ID,$this-> ;行1);
// $this->行 1 の詳細情報は $this->num_rows()、
// しかし、すべての場合に機能するとは限りません (複雑な選択)
// そしてそれはここでは非常に遅いです
}
$this->Row =1;
$errno=ora_errorcode($this->Query_ID);
if(1403 == $errno) { # 1043 は、これ以上レコードが見つからないことを意味します
$this->Errno=0;
$this->エラー="";
$this->disconnect();
$stat=0;
} else {
$this->Error=ora_error($this->Query_ID);
$this->Errno=$errno;
if($this->Debug) {
printf("
%d エラー: %s",
$this->Errno,
$this->Error );
}
$stat=0;
}
} else {
$this->ora_no_next_fetch=false;
for($ix=0;$ix
$col=strto lower(ora_columnname($this->Query_ID,$ix));
$value=ora_getcolumn($this->Query_ID,$ix);
$this->Record[ "$col" ] = $value;
$this->レコード[ $ix ] = $value;
#DBG echo"[$col]: $value
n";
}
$stat=1;
}
return $stat;
}
## look() は $pos - 1 と $pos に対してのみ機能します
## おそらく独自の実装を作成しますが、私の
## の意見は、これはそうすべきであるということですPHP3 によって実行されます。
function look($pos) {
if ($this->Row - 1 == $pos) {
$this->gt;ora_no_next_fetch=true;
} elseif ($this->Row == $pos ) {
## 何もしません
} else {
$this->halt("無効なシーク(): 位置はできませんAPI によって処理されます。
".
"このバージョンでは最後の要素へのシークのみが許可されています
".
"差が大きすぎます。募集: $pos 現在の位置: $this- >行");
}
if ($this->Debug) echo "
Debug: Seek = $pos
";
$this->Row=$pos;
}
function lock($table, $mode = "write") {
if ($mode == "write") {
$result = ora_do($this-> ;Link_ID, "行排他モードでテーブル $table をロック");
} else {
$result = 1;
}
$result を返す;
}
functionunlock() {
return ora_do($this->Link_ID, "commit");
}
// 重要な注意: この関数は Oracle-Database-Links では機能しません。
// より良い方法を自由に入手できます。 :)
関数メタデータ($table,$full=false) {
$count = 0;
$id = 0;
$res = array();
/*
* Table との互換性の問題のため、metadata() の動作
* を変更しました。
* $full に応じて、メタデータは次の値を返します:
*
* - full は false (デフォルト):
* $result[]:
* [0]["table "] テーブル名
* [0]["name"] フィールド名
* [0]["type"] フィールドの種類
* [0]["len"] フィールドの長さ
* [0]["flags"] フィールド フラグ ("NOT NULL"、"INDEX")
* [0]["format"] 数値の精度と位取り (例: "10,2") または空
* [0]["index"] インデックスの名前 (存在する場合)
* [0]["chars"] 文字数 (char 型がある場合)
*
* - 完全true です
* $result[]:
* ["num_fields"] メタデータ レコードの数
* [0]["table"] テーブル名
* [0]["name"]フィールド名
* [0]["type"] フィールドタイプ
* [0]["len"] フィールド長
* [0]["flags"] フィールドフラグ ("NOT NULL"、 "INDEX")
* [0]["format"] 数値の精度とスケール (例: "10,2") または空の
* [0]["index"] インデックスの名前 (がある場合) 1)
* [0]["chars"] 文字の数 (char-type がある場合)
* [0]["php_type"] 対応する PHP タイプ
* [0][" php_subtype"] PHP タイプのサブタイプ
* ["meta"][フィールド名] "フィールド名" という名前のフィールドのインデックス
* これは、名前はあるが、index-num がない場合に使用できます。非常に高速
* テスト: if (isset($result['meta']['myfield'])) {} ...
*/
$this->connect() ;
## これは RIGHT OUTER JOIN です: "( )"。
## このクエリの結果を確認したい場合は、次のことを試してください。
## $table = new Table; $db = 新しい my_DB_Sql; #
## # 独自のクラスを作成する必要があります
## $table->show_results($db->query(クエリ vvvvvv を参照))
##
$this-> ;query("SELECT T.table_name,T.column_name,T.data_type,".
"T.data_length,T.data_precision,T.data_scale,T.nullable,".
"T.char_col_decl_length,I .index_name".
" FROM ALL_TAB_COLUMNS T,ALL_IND_COLUMNS I".
" WHERE T.column_name=I.column_name ( )".
" AND T.table_name=I.table_name ( )".
" AND T.table_name=UPPER('$table') ORDER BY T.column_id");
$i=0;
while ($this->next_record()) {
$res[$i]["table"] = $this->Record[table_name];
$res[$i]["name"] = strto lower($this->Record[column_name]);
$res[$i]["type"] = $this->Record[data_type];
$res[$i]["len"] = $this->Record[data_length];
if ($this->Record[index_name]) $res[$i]["flags"] = "INDEX ";
$res[$i]["flags"] .= ( $this->Record[nullable] == 'N') ? '' : 'NOT NULL';
$res[$i]["format"]= (int)$this->Record[data_precision].",".
(int)$this->レコード[データスケール];
if ("0,0"==$res[$i]["format"]) $res[$i]["format"]='';
$res[$i]["index"] = $this->Record[index_name];
$res[$i]["chars"] = $this->Record[char_col_decl_length];
if ($full) {
$j=$res[$i]["名前"];
$res["meta"][$j] = $i;
$res["meta"][strtoupper($j)] = $i;
switch ($res[$i]["type"]) {
case "VARCHAR2" :
case "VARCHAR" :
case "CHAR" :
$res["php_type "]="文字列";
$res["php_subtype"]="";
休憩;
ケース "DATE" :
$res["php_type"]="string";
$res["php_subtype"]="日付";
休憩;
ケース "BLOB" :
ケース "CLOB" :
ケース "BFILE" :
ケース "RAW" :
ケース "LONG" :
ケース "LONG RAW" :
$res["php_type"]="string";
$res["php_subtype"]="blob";
休憩;
case "NUMBER" :
if ($res[$i]["format"]) {
$res["php_type"]="double";
$res["php_subtype"]="";
} else {
$res["php_type"]="int";
$res["php_subtype"]="";
}
休憩;
デフォルト :
$this->halt("metadata(): タイプが有効な値ではありません: '$res[$i][type]'");
休憩;
}
}
if ($full) $res["meta"][$res[$i]["name"]] = $i;
$i ;
}
if ($full) $res["num_fields"]=$i;
# $this->disconnect();
$res を返す;
}
## この機能はテストされていません!
functionaffected_rows() {
if ($this->Debug) echo "
Debug:affected_rows="。 ora_numrows($this->Query_ID)."
";
return ora_numrows($this->Query_ID);
}
## 既知のバグ: SELECT DISTINCT および結果の行に依存するその他の
## 構造では機能しません。
## したがって、
## が機能するかどうか、作成したすべてのクエリを *本当に確認する必要があります。
##
## また、修飾された置換の場合、
## 選択を解析する必要があります。これは失敗します: "SELECT id, from FROM ...")。
## "from" は、私が知る限り Oracle のキーワードであるため、
## はこの方法でのみ使用できます。しかし、あなたは警告を受けています。
function num_rows() {
$curs=ora_open($this->Link_ID);
## これは重要な部分であり、ハックでもあります。
if (eregi("^[[:space:]]*SELECT[[:space:]]",$this->lastQuery) )
{
# これはすべてに機能します?? SELECT DISTINCT ケースを含むケース。
# 元の SQL 式から select count(*) を作成するだけです
# 速度を上げるために ORDER BY (存在する場合) を削除します
# 正規表現も好きです ;-)))
$q = sprintf("SELECT COUNT(*) FROM (%s)",
@eregi_Replace("ORDER[[:space:]] BY[^)]*()*)", "1",
$ this->lastQuery)
);
# は副選択にも機能します:
# if (eregi("[[:space:]] FROM([[:space:]] .*[[:space:]] FROM)", $this->lastQuery,$r))
# $areplace=$r[1];
# $q=eregi_Replace("^[[:space:]]*SELECT[[:space:]] ".
# ".*[[:space:]] FROM",
# "SELECT COUNT(*) FROM$areplace",
# $this->lastQuery);
if ($this->Debug) echo "
Debug: num_rows: $q
";
ORA_parse($curs,$q);
ORA_exec($curs);
ORA_fetch($curs);
$result = ORA_getcolumn($curs,0);
ORA_close($curs);
if ($this->Debug)
{
echo "
Debug: ID ".$this->QueryID。
" num_rows="。 $result ."
";
}
$result を返す;
}
else
{
$this->halt("最後のクエリは SELECT ではありませんでした: $this->lastQuery");
}
}
function num_fields() {
if ($this->Debug) echo "
Debug: num_fields="。 ora_numcols($this->Query_ID) 。 "
";
return ora_numcols($this->Query_ID);
}
function nf() {
return $this->num_rows();
}
function np() {
print $this->num_rows();
}
function f($Name) {
return $this->Record[$Name];
}
function p($Name) {
print $this->Record[$Name];
}
/* public: シーケンス番号 */
function nextid($seq_name)
{
$this->connect();
/* 独立したクエリ ID */
$Query_ID = ora_open($this->Link_ID);
if(!@ora_parse($Query_ID,"SELECT $seq_name.NEXTVAL FROM DUAL"))
{
// そのようなシーケンスはまだないので、作成します
if( !@ora_parse($Query_ID,"CREATE SEQUENCE $seq_name")
!@ora_exec($Query_ID)
)
{
$this->halt("
nextid() 関数 - シーケンスを作成できません");
0 を返す;
}
@ora_parse($Query_ID,"SELECT $seq_name.NEXTVAL FROM DUAL");
}
if (!@ora_exec($Query_ID)) {
$this->halt("
ora_exec() が失敗しました:
nextID 関数");
}
if (@ora_fetch($Query_ID) ) {
$next_id = ora_getcolumn($Query_ID, 0);
}
else {
$next_id = 0;
}
if ( $Query_ID > 0 ) {
ora_close($Query_ID);
}
$next_id を返す;
}
functiondetach() {
if($this->Debug) {
echo "デバッグ: $this->Query_ID の接続を切断しています...
n ";
}
if ( $this->Query_ID < 1 ) {
echo "警告:切断(): ID $this->Query_IDn を解放できません";
# return();
}
ora_close($this->Query_ID);
$this->Query_ID=0;
}
/* private: エラー処理 */
function halt($msg) {
if ($this->Halt_On_Error == "no")
return;
$this->haltmsg($msg);
if ($this->Halt_On_Error != "レポート")
die("セッションが停止しました。");
}
function haltmsg($msg) {
printf("
データベース エラー: %s
n", $msg);
printf("Oracle エラー: %s (%s)
n",
$this->Errno,
$this->Error) ;
}
関数 table_names() {
$this->connect();
$this->query("
SELECT table_name,tablespace_name
FROM user_tables");
$i=0;
while ($this->next_record())
{
$info[$i]["table_name"] =$this->Record["table_name"];
$info[$i]["テーブルスペース名"]=$this->Record["テーブルスペース名"];
$i ;
}
$info を返します。
}
// 一部のトランザクションのサポート
// メソッドは ct_oracle.inc で使用されます
function begin_transaction()
{
$this->connect ();
// ここで、自動コミットを無効にします
Ora_CommitOff($this->Link_ID);
if ($this->Debug)
{
print "BEGIN TRANSACTION
";
}
}
function end_transaction()
{
if ($this->Debug)
{
print "BEGIN TRANSACTION
";
}
$res = 1;
if(!@Ora_Commit($this->Link_ID))
{
Ora_CommitOn($this->Link_ID);
$this->halt("トランザクションを終了できません");
$res = 0;
}
// 自動コミットを再度有効にします
Ora_CommitOn($this->Link_ID);
if ($this->Debug)
{
print "END TRANSACTION : $res
";
}
$res を返す;
}
}
?>