You are currently browsing the archives of 乱七八糟 .

php 数据库操作类

  1. <?php
  2. class DB_Sql
  3. {
  4.  
  5. /* public: connection parameters */
  6. var $Host = "";
  7. var $Database = "";
  8. var $User = "";
  9. var $Password = "";
  10.  
  11. /* public: configuration parameters */
  12. var $Auto_Free = 1; ## Set to 1 for automatic mysql_free_result()
  13. var $Debug = 0; ## Set to 1 for debugging messages.
  14. var $Halt_On_Error = "yes"; ## "yes" (halt with message), "no" (ignore errors quietly), "report" (ignore errror, but spit a warning)
  15. var $PConnect = 0; ## Set to 1 to use persistent database connections
  16. var $Seq_Table = "db_sequence";
  17.  
  18. /* public: result array and current row number */
  19. var $Record = array();
  20. var $Row;
  21.  
  22. /* public: current error number and error text */
  23. var $Errno = 0;
  24. var $Error = "";
  25.  
  26. /* public: this is an api revision, not a CVS revision. */
  27. var $type = "mysql";
  28. //var $revision = "1.2";
  29.  
  30. /* private: link and query handles */
  31. var $Link_ID = 0;
  32. var $Query_ID = 0;
  33.  
  34. var $locked = false; ## set to true while we have a lock
  35.  
  36. /* public: constructor */
  37. function DB_Sql() {
  38. $this-&gt;query($query);
  39. }
  40.  
  41. /* public: some trivial reporting */
  42. function link_id() {
  43. return $this-&gt;Link_ID;
  44. }
  45.  
  46. function query_id() {
  47. return $this-&gt;Query_ID;
  48. }
  49.  
  50. /* public: connection management */
  51. function connect($Database = "", $Host = "", $User = "", $Password = "") {
  52. /* Handle defaults */
  53. if ("" == $Database)
  54. $Database = $this-&gt;Database;
  55.  
  56. if ("" == $Host)
  57. $Host = $this-&gt;Host;
  58.  
  59. if ("" == $User)
  60. $User = $this-&gt;User;
  61.  
  62. if ("" == $Password)
  63. $Password = $this-&gt;Password;
  64.  
  65. /* establish connection, select database */
  66. if ( 0 == $this-&gt;Link_ID ) {
  67.  
  68. if(!$this-&gt;PConnect) {
  69. $this-&gt;Link_ID = mysql_connect($Host, $User, $Password);
  70. } else {
  71. $this-&gt;Link_ID = mysql_pconnect($Host, $User, $Password);
  72. }
  73. if (!$this-&gt;Link_ID) {
  74. $this-&gt;halt("connect($Host, $User, \$Password) failed.");
  75. return 0;
  76. }
  77.  
  78. if (!@mysql_select_db($Database,$this-&gt;Link_ID)) {
  79. $this-&gt;halt("cannot use database ".$Database);
  80. return 0;
  81. }
  82. }
  83.  
  84. return $this-&gt;Link_ID;
  85. }
  86.  
  87. /* public: discard the query result */
  88. function free() {
  89. @mysql_free_result($this-&gt;Query_ID);
  90. $this-&gt;Query_ID = 0;
  91. }
  92.  
  93. /* public: perform a query */
  94. function query($Query_String) {
  95. /* No empty queries, please, since Php4 chokes on them. */
  96. if ($Query_String == "")
  97. /* The empty query string is passed on from the constructor,
  98. * when calling the class without a query, e.g. in situations
  99. * like these: '$db = new DB_Sql_Subclass;'
  100. */
  101. return 0;
  102.  
  103. if (!$this-&gt;connect()) {
  104. return 0; /* we already complained in connect() about that. */
  105. };
  106.  
  107. # New query, discard previous result.
  108. if ($this-&gt;Query_ID) {
  109. $this-&gt;free();
  110. }
  111.  
  112. if ($this-&gt;Debug)
  113. printf("Debug: query = %s
  114. \n", $Query_String);
  115.  
  116. $this-&gt;Query_ID = @mysql_query($Query_String,$this-&gt;Link_ID);
  117. $this-&gt;Row = 0;
  118. $this-&gt;Errno = mysql_errno();
  119. $this-&gt;Error = mysql_error();
  120. if (!$this-&gt;Query_ID) {
  121. $this-&gt;halt("Invalid SQL: ".$Query_String);
  122. }
  123.  
  124. # Will return nada if it fails. That's fine.
  125. return $this-&gt;Query_ID;
  126. }
  127.  
  128. /* public: walk result set */
  129. function next_record() {
  130. if (!$this-&gt;Query_ID) {
  131. $this-&gt;halt("next_record called with no query pending.");
  132. return 0;
  133. }
  134.  
  135. $this-&gt;Record = @mysql_fetch_array($this-&gt;Query_ID);
  136. $this-&gt;Row += 1;
  137. $this-&gt;Errno = mysql_errno();
  138. $this-&gt;Error = mysql_error();
  139.  
  140. $stat = is_array($this-&gt;Record);
  141. if (!$stat &amp;&amp; $this-&gt;Auto_Free) {
  142. $this-&gt;free();
  143. }
  144. return $stat;
  145. }
  146.  
  147. /* public: position in result set */
  148. function seek($pos = 0) {
  149. $status = @mysql_data_seek($this-&gt;Query_ID, $pos);
  150. if ($status)
  151. $this-&gt;Row = $pos;
  152. else {
  153. $this-&gt;halt("seek($pos) failed: result has ".$this-&gt;num_rows()." rows.");
  154.  
  155. /* half assed attempt to save the day,
  156. * but do not consider this documented or even
  157. * desireable behaviour.
  158. */
  159. @mysql_data_seek($this-&gt;Query_ID, $this-&gt;num_rows());
  160. $this-&gt;Row = $this-&gt;num_rows();
  161. return 0;
  162. }
  163.  
  164. return 1;
  165. }
  166.  
  167. /* public: table locking */
  168. function lock($table, $mode = "write") {
  169. $query = "lock tables ";
  170. if(is_array($table)) {
  171. while(list($key,$value) = each($table)) {
  172. // text keys are "read", "read local", "write", "low priority write"
  173. if(is_int($key)) $key = $mode;
  174. if(strpos($value, ",")) {
  175. $query .= str_replace(",", " $key, ", $value) . " $key, ";
  176. } else {
  177. $query .= "$value $key, ";
  178. }
  179. }
  180. $query = substr($query, 0, -2);
  181. } elseif(strpos($table, ",")) {
  182. $query .= str_replace(",", " $mode, ", $table) . " $mode";
  183. } else {
  184. $query .= "$table $mode";
  185. }
  186. if(!$this-&gt;query($query)) {
  187. $this-&gt;halt("lock() failed.");
  188. return false;
  189. }
  190. $this-&gt;locked = true;
  191. return true;
  192. }
  193.  
  194. function unlock() {
  195.  
  196. // set before unlock to avoid potential loop
  197. $this-&gt;locked = false;
  198.  
  199. if(!$this-&gt;query("unlock tables")) {
  200. $this-&gt;halt("unlock() failed.");
  201. return false;
  202. }
  203. return true;
  204. }
  205.  
  206. /* public: evaluate the result (size, width) */
  207. function affected_rows() {
  208. return @mysql_affected_rows($this-&gt;Link_ID);
  209. }
  210.  
  211. function num_rows() {
  212. return @mysql_num_rows($this-&gt;Query_ID);
  213. }
  214.  
  215. function num_fields() {
  216. return @mysql_num_fields($this-&gt;Query_ID);
  217. }
  218.  
  219. /* public: shorthand notation */
  220. function nf() {
  221. return $this-&gt;num_rows();
  222. }
  223.  
  224. function np() {
  225. print $this-&gt;num_rows();
  226. }
  227.  
  228. function f($Name) {
  229. if (isset($this-&gt;Record[$Name])) {
  230. return $this-&gt;Record[$Name];
  231. }
  232. }
  233.  
  234. function p($Name) {
  235. if (isset($this-&gt;Record[$Name])) {
  236. print $this-&gt;Record[$Name];
  237. }
  238. }
  239.  
  240. /* public: sequence numbers */
  241. function nextid($seq_name) {
  242. /* if no current lock, lock sequence table */
  243. if(!$this-&gt;locked) {
  244. if($this-&gt;lock($this-&gt;Seq_Table)) {
  245. $locked = true;
  246. } else {
  247. $this-&gt;halt("cannot lock ".$this-&gt;Seq_Table." - has it been created?");
  248. return 0;
  249. }
  250. }
  251.  
  252. /* get sequence number and increment */
  253. $q = sprintf("select nextid from %s where seq_name = '%s'",
  254. $this-&gt;Seq_Table,
  255. $seq_name);
  256. if(!$this-&gt;query($q)) {
  257. $this-&gt;halt('query failed in nextid: '.$q);
  258. return 0;
  259. }
  260.  
  261. /* No current value, make one */
  262. if(!$this-&gt;next_record()) {
  263. $currentid = 0;
  264. $q = sprintf("insert into %s values('%s', %s)",
  265. $this-&gt;Seq_Table,
  266. $seq_name,
  267. $currentid);
  268. if(!$this-&gt;query($q)) {
  269. $this-&gt;halt('query failed in nextid: '.$q);
  270. return 0;
  271. }
  272. } else {
  273. $currentid = $this-&gt;f("nextid");
  274. }
  275. $nextid = $currentid + 1;
  276. $q = sprintf("update %s set nextid = '%s' where seq_name = '%s'",
  277. $this-&gt;Seq_Table,
  278. $nextid,
  279. $seq_name);
  280. if(!$this-&gt;query($q)) {
  281. $this-&gt;halt('query failed in nextid: '.$q);
  282. return 0;
  283. }
  284.  
  285. /* if nextid() locked the sequence table, unlock it */
  286. if($locked) {
  287. $this-&gt;unlock();
  288. }
  289.  
  290. return $nextid;
  291. }
  292.  
  293. /* public: return table metadata */
  294. function metadata($table = "", $full = false) {
  295. $count = 0;
  296. $id = 0;
  297. $res = array();
  298.  
  299. /*
  300. * Due to compatibility problems with Table we changed the behavior
  301. * of metadata();
  302. * depending on $full, metadata returns the following values:
  303. *
  304. * - full is false (default):
  305. * $result[]:
  306. * [0]["table"] table name
  307. * [0]["name"] field name
  308. * [0]["type"] field type
  309. * [0]["len"] field length
  310. * [0]["flags"] field flags
  311. *
  312. * - full is true
  313. * $result[]:
  314. * ["num_fields"] number of metadata records
  315. * [0]["table"] table name
  316. * [0]["name"] field name
  317. * [0]["type"] field type
  318. * [0]["len"] field length
  319. * [0]["flags"] field flags
  320. * ["meta"][field name] index of field named "field name"
  321. * This last one could be used if you have a field name, but no index.
  322. * Test: if (isset($result['meta']['myfield'])) { ...
  323. */
  324.  
  325. // if no $table specified, assume that we are working with a query
  326. // result
  327. if ($table) {
  328. $this-&gt;connect();
  329. $id = @mysql_list_fields($this-&gt;Database, $table);
  330. if (!$id) {
  331. $this-&gt;halt("Metadata query failed.");
  332. return false;
  333. }
  334. } else {
  335. $id = $this-&gt;Query_ID;
  336. if (!$id) {
  337. $this-&gt;halt("No query specified.");
  338. return false;
  339. }
  340. }
  341.  
  342. $count = @mysql_num_fields($id);
  343.  
  344. // made this IF due to performance (one if is faster than $count if's)
  345. if (!$full) {
  346. for ($i=0; $i&lt;$count; $i++) {
  347. $res[$i]["table"] = @mysql_field_table ($id, $i);
  348. $res[$i]["name"] = @mysql_field_name ($id, $i);
  349. $res[$i]["type"] = @mysql_field_type ($id, $i);
  350. $res[$i]["len"] = @mysql_field_len ($id, $i);
  351. $res[$i]["flags"] = @mysql_field_flags ($id, $i);
  352. }
  353. } else { // full
  354. $res["num_fields"]= $count;
  355.  
  356. for ($i=0; $i&lt;$count; $i++) {
  357. $res[$i]["table"] = @mysql_field_table ($id, $i);
  358. $res[$i]["name"] = @mysql_field_name ($id, $i);
  359. $res[$i]["type"] = @mysql_field_type ($id, $i);
  360. $res[$i]["len"] = @mysql_field_len ($id, $i);
  361. $res[$i]["flags"] = @mysql_field_flags ($id, $i);
  362. $res["meta"][$res[$i]["name"]] = $i;
  363. }
  364. }
  365.  
  366. // free the result only if we were called on a table
  367. if ($table) {
  368. @mysql_free_result($id);
  369. }
  370. return $res;
  371. }
  372.  
  373. /* public: find available table names */
  374. function table_names() {
  375. $this-&gt;connect();
  376. $h = @mysql_query("show tables", $this-&gt;Link_ID);
  377. $i = 0;
  378. while ($info = @mysql_fetch_row($h)) {
  379. $return[$i]["table_name"] = $info[0];
  380. $return[$i]["tablespace_name"] = $this-&gt;Database;
  381. $return[$i]["database"] = $this-&gt;Database;
  382. $i++;
  383. }
  384.  
  385. @mysql_free_result($h);
  386. return $return;
  387. }
  388.  
  389. /* private: error handling */
  390. function halt($msg) {
  391. $this-&gt;Error = @mysql_error($this-&gt;Link_ID);
  392. $this-&gt;Errno = @mysql_errno($this-&gt;Link_ID);
  393.  
  394. if ($this-&gt;locked) {
  395. $this-&gt;unlock();
  396. }
  397.  
  398. if ($this-&gt;Halt_On_Error == "no")
  399. return;
  400.  
  401. $this-&gt;haltmsg($msg);
  402.  
  403. if ($this-&gt;Halt_On_Error != "report")
  404. die("Session halted.");
  405. }
  406.  
  407. function haltmsg($msg) {
  408. printf("
  409.  
  410. <strong>Database error:</strong> %s
  411. \n", $msg);
  412. printf("<strong>MySQL Error</strong>: %s (%s)
  413. \n",
  414. $this-&gt;Errno,
  415. $this-&gt;Error);
  416. }
  417.  
  418. //----------------------------------
  419. // 模块: 自定义函数
  420. // 功能: 部分实用的数据库处理方法
  421. // 作者: heiyeluren
  422. // 时间: 2005-12-26
  423. //----------------------------------
  424.  
  425. /**
  426. * 方法: execute($sql)
  427. * 功能: 执行一条SQL语句,主要针对没有结果集返回的SQL
  428. * 参数: $sql 需要执行的SQL语句,例如:execute("DELETE FROM table1 WHERE id = '1'")
  429. * 返回: 更新成功返回True,失败返回False
  430. */
  431. function execute($sql)
  432. {
  433. if (empty($sql))
  434. {
  435. $this-&gt;error("Invalid parameter");
  436. }
  437. if (!$this-&gt;query($sql))
  438. {
  439. return false;
  440. }
  441. return true;
  442. }
  443.  
  444. /**
  445. * 方法: get_all($sql)
  446. * 功能: 获取SQL执行的所有记录
  447. * 参数: $sql 需要执行的SQL,例如: get_all("SELECT * FROM Table1")
  448. * 返回: 返回包含所有查询结果的二维数组
  449. */
  450. function get_all($sql)
  451. {
  452. $this-&gt;query($sql);
  453. $result_array = array();
  454. while($this-&gt;next_record())
  455. {
  456.  
  457. $result_array[] = $this-&gt;Record;
  458. }
  459. if (count($result_array)&lt;=0)
  460. {
  461. return 0;
  462. }
  463. return $result_array;
  464. }
  465.  
  466. /**
  467. * 方法: get_one($sql)
  468. * 功能: 获取SQL执行的一条记录
  469. * 参数: $sql 需要执行的SQL,例如: get_one("SELECT * FROM Table1 WHERE id = '1'")
  470. * 返回: 返回包含一条查询结果的一维数组
  471. */
  472. function get_one($sql)
  473. {
  474. $this-&gt;query($sql);
  475. if (!$this-&gt;next_record())
  476. {
  477. return 0;
  478. }
  479. return $this-&gt;Record;
  480. }
  481.  
  482. /**
  483. * 方法: get_limit($sql, $limit)
  484. * 功能: 获取SQL执行的指定数量的记录
  485. * 参数:
  486. * $sql 需要执行的SQL,例如: SELECT * FROM Table1
  487. * $limit 需要限制的记录数
  488. * 例如 需要获取10条记录, get_limit("SELECT * FROM Table1", 10);
  489. *
  490. * 返回: 返回包含所有查询结果的二维数组
  491. */
  492. function get_limit($sql, $limit)
  493. {
  494. $this-&gt;query($sql);
  495. $result_array = array();
  496. for ($i=0; $i&lt;$limit&amp;&amp;$this-&gt;next_record(); $i++)
  497. {
  498. $result_array[] = $this-&gt;Record;
  499. }
  500. if (count($result_array) &lt;= 0)
  501. {
  502. return 0;
  503. }
  504. return $result_array;
  505. }
  506.  
  507. /**
  508. * 方法: limit_query($sql, $start=0, $offset=20, $order="")
  509. * 功能: 为分页的获取SQL执行的指定数量的记录
  510. * 参数:
  511. * $sql 需要执行的SQL,例如: SELECT * FROM Table1
  512. * $start 记录的开始数, 缺省为0
  513. * $offset 记录的偏移量,缺省为20
  514. * $order 排序方式,缺省为空,例如:ORDER BY id DESC
  515. * 例如 需要获取从0到10的记录并且按照ID号倒排, get_limit("SELECT * FROM Table1", 0, 10, "ORDER BY id DESC");
  516. *
  517. * 返回: 返回包含所有查询结果的二维数组
  518. */
  519. function limit_query($sql, $start=0, $offset=20, $order="")
  520. {
  521. $sql = $sql ." $order LIMIT $start,$offset";
  522. $this-&gt;query($sql);
  523. $result = array();
  524. while($this-&gt;next_record())
  525. {
  526. $result[] = $this-&gt;Record;
  527. }
  528. if (count($result) &lt;=0 )
  529. {
  530. return 0;
  531. }
  532. return $result;
  533. }
  534.  
  535. /**
  536. * 方法: count($table,$field="*", $where="")
  537. * 功能: 统计表中数据总数
  538. * 参数:
  539. * $table 需要统计的表名
  540. * $field 需要统计的字段,默认为*
  541. * $where 条件语句,缺省为空
  542. * 例如 按照ID统计所有年龄小于20岁的用户, count("user_table", "id", "user_age &lt; 20")
  543. *
  544. * 返回: 返回统计结果的数字
  545. */
  546. function count($table,$field="*", $where="")
  547. {
  548. $sql = (empty($where) ? "SELECT COUNT($field) FROM $table" : "SELECT COUNT($field) FROM $table WHERE $where");
  549. $result = $this-&gt;get_one($sql);
  550. if (!is_array($result))
  551. {
  552. return 0;
  553. }
  554. return $result[0];
  555. }
  556.  
  557. /**
  558. * 方法: insert($table,$dataArray)
  559. * 功能: 插入一条记录到表里
  560. * 参数:
  561. * $table 需要插入的表名
  562. * $dataArray 需要插入字段和值的数组,键为字段名,值为字段值,例如:array("user_name"=&gt;"张三", "user_age"=&gt;"20岁");
  563. * 例如 比如插入用户张三,年龄为20, insert("users", array("user_name"=&gt;"张三", "user_age"=&gt;"20岁"))
  564. *
  565. * 返回: 插入记录成功返回True,失败返回False
  566. */
  567. function insert($table,$dataArray)
  568. {
  569. if (!is_array($dataArray) || count($dataArray)&lt;=0)
  570. {
  571. $this-&gt;error("Invalid parameter");
  572. }
  573. while(list($key,$val) = each($dataArray))
  574. {
  575. $field .= "$key,";
  576. $value .= "'$val',";
  577. }
  578. $field = substr($field, 0, -1);
  579. $value = substr($value, 0, -1);
  580. $sql = "INSERT INTO $table ($field) VALUES ($value)";
  581. if (!$this-&gt;query($sql))
  582. {
  583. return false;
  584. }
  585. return true;
  586. }
  587.  
  588. /**
  589. * 方法: update($talbe, $dataArray, $where)
  590. * 功能: 更新一条记录
  591. * 参数:
  592. * $table 需要更新的表名
  593. * $dataArray 需要更新字段和值的数组,键为字段名,值为字段值,例如:array("user_name"=&gt;"张三", "user_age"=&gt;"20岁");
  594. * $where 条件语句
  595. * 例如 比如更新姓名为张三的用户为李四,年龄为21
  596. * update("users", array("user_name"=&gt;"张三", "user_age"=&gt;"20岁"), "user_name='张三'")
  597. *
  598. * 返回: 更新成功返回True,失败返回False
  599. */
  600. function update($talbe, $dataArray, $where)
  601. {
  602. if (!is_array($dataArray) || count($dataArray)&lt;=0)
  603. {
  604. $this-&gt;error("Invalid parameter");
  605. }
  606. while(list($key,$val) = each($dataArray))
  607. {
  608. $value .= "$key = '$val',";
  609. }
  610. $value = substr($value, 0, -1);
  611. $sql = "UPDATE $talbe SET $value WHERE $where";
  612. if (!$this-&gt;query($sql))
  613. {