Sqlsrv.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. namespace think\db\connector;
  12. use PDO;
  13. use think\db\Connection;
  14. use think\db\Query;
  15. /**
  16. * Sqlsrv数据库驱动
  17. */
  18. class Sqlsrv extends Connection
  19. {
  20. // PDO连接参数
  21. protected $params = [
  22. PDO::ATTR_CASE => PDO::CASE_NATURAL,
  23. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  24. PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
  25. PDO::ATTR_STRINGIFY_FETCHES => false,
  26. ];
  27. protected $builder = '\\think\\db\\builder\\Sqlsrv';
  28. /**
  29. * 解析pdo连接的dsn信息
  30. * @access protected
  31. * @param array $config 连接信息
  32. * @return string
  33. */
  34. protected function parseDsn($config)
  35. {
  36. $dsn = 'sqlsrv:Database=' . $config['database'] . ';Server=' . $config['hostname'];
  37. if (!empty($config['hostport'])) {
  38. $dsn .= ',' . $config['hostport'];
  39. }
  40. return $dsn;
  41. }
  42. /**
  43. * 取得数据表的字段信息
  44. * @access public
  45. * @param string $tableName
  46. * @return array
  47. */
  48. public function getFields($tableName)
  49. {
  50. list($tableName) = explode(' ', $tableName);
  51. $tableNames = explode('.', $tableName);
  52. $tableName = isset($tableNames[1]) ? $tableNames[1] : $tableNames[0];
  53. $sql = "SELECT column_name, data_type, column_default, is_nullable
  54. FROM information_schema.tables AS t
  55. JOIN information_schema.columns AS c
  56. ON t.table_catalog = c.table_catalog
  57. AND t.table_schema = c.table_schema
  58. AND t.table_name = c.table_name
  59. WHERE t.table_name = '$tableName'";
  60. $pdo = $this->query($sql, [], false, true);
  61. $result = $pdo->fetchAll(PDO::FETCH_ASSOC);
  62. $info = [];
  63. if ($result) {
  64. foreach ($result as $key => $val) {
  65. $val = array_change_key_case($val);
  66. $info[$val['column_name']] = [
  67. 'name' => $val['column_name'],
  68. 'type' => $val['data_type'],
  69. 'notnull' => (bool) ('' === $val['is_nullable']), // not null is empty, null is yes
  70. 'default' => $val['column_default'],
  71. 'primary' => false,
  72. 'autoinc' => false,
  73. ];
  74. }
  75. }
  76. $sql = "SELECT column_name FROM information_schema.key_column_usage WHERE table_name='$tableName'";
  77. // 调试开始
  78. $this->debug(true);
  79. $pdo = $this->linkID->query($sql);
  80. // 调试结束
  81. $this->debug(false, $sql);
  82. $result = $pdo->fetch(PDO::FETCH_ASSOC);
  83. if ($result) {
  84. $info[$result['column_name']]['primary'] = true;
  85. }
  86. return $this->fieldCase($info);
  87. }
  88. /**
  89. * 取得数据表的字段信息
  90. * @access public
  91. * @param string $dbName
  92. * @return array
  93. */
  94. public function getTables($dbName = '')
  95. {
  96. $sql = "SELECT TABLE_NAME
  97. FROM INFORMATION_SCHEMA.TABLES
  98. WHERE TABLE_TYPE = 'BASE TABLE'
  99. ";
  100. $pdo = $this->query($sql, [], false, true);
  101. $result = $pdo->fetchAll(PDO::FETCH_ASSOC);
  102. $info = [];
  103. foreach ($result as $key => $val) {
  104. $info[$key] = current($val);
  105. }
  106. return $info;
  107. }
  108. /**
  109. * 得到某个列的数组
  110. * @access public
  111. * @param Query $query 查询对象
  112. * @param string $field 字段名 多个字段用逗号分隔
  113. * @param string $key 索引
  114. * @return array
  115. */
  116. public function column(Query $query, $field, $key = '')
  117. {
  118. $options = $query->getOptions();
  119. if (empty($options['fetch_sql']) && !empty($options['cache'])) {
  120. // 判断查询缓存
  121. $cache = $options['cache'];
  122. $guid = is_string($cache['key']) ? $cache['key'] : $this->getCacheKey($query, $field);
  123. $result = Container::get('cache')->get($guid);
  124. if (false !== $result) {
  125. return $result;
  126. }
  127. }
  128. if (isset($options['field'])) {
  129. $query->removeOption('field');
  130. }
  131. if (is_null($field)) {
  132. $field = '*';
  133. } elseif ($key && '*' != $field) {
  134. $field = $key . ',' . $field;
  135. }
  136. if (is_string($field)) {
  137. $field = array_map('trim', explode(',', $field));
  138. }
  139. $query->setOption('field', $field);
  140. // 生成查询SQL
  141. $sql = $this->builder->select($query);
  142. $bind = $query->getBind();
  143. if (!empty($options['fetch_sql'])) {
  144. // 获取实际执行的SQL语句
  145. return $this->getRealSql($sql, $bind);
  146. }
  147. // 执行查询操作
  148. $pdo = $this->query($sql, $bind, $options['master'], true);
  149. if (1 == $pdo->columnCount()) {
  150. $result = $pdo->fetchAll(PDO::FETCH_COLUMN);
  151. } else {
  152. $resultSet = $pdo->fetchAll(PDO::FETCH_ASSOC);
  153. if ('*' == $field && $key) {
  154. $result = array_column($resultSet, null, $key);
  155. } elseif ($resultSet) {
  156. $fields = array_keys($resultSet[0]);
  157. $count = count($fields);
  158. $key1 = array_shift($fields);
  159. $key2 = $fields ? array_shift($fields) : '';
  160. $key = $key ?: $key1;
  161. if (strpos($key, '.')) {
  162. list($alias, $key) = explode('.', $key);
  163. }
  164. if (3 == $count) {
  165. $column = $key2;
  166. } elseif ($count < 3) {
  167. $column = $key1;
  168. } else {
  169. $column = null;
  170. }
  171. $result = array_column($resultSet, $column, $key);
  172. } else {
  173. $result = [];
  174. }
  175. }
  176. if (isset($cache) && isset($guid)) {
  177. // 缓存数据
  178. $this->cacheData($guid, $result, $cache);
  179. }
  180. return $result;
  181. }
  182. /**
  183. * SQL性能分析
  184. * @access protected
  185. * @param string $sql
  186. * @return array
  187. */
  188. protected function getExplain($sql)
  189. {
  190. return [];
  191. }
  192. }