13

私が探しているのは、次のようなフォーマットされていないクエリを受け取る php 関数です。

$sql = "color = 'green' のものから名前、サイズを選択 価格 asc 順";

次のような HTML ページに表示されるようにします。

選択する
    名前、サイズ
から
    もの
どこ
    色 = '緑'
オーダーバイ
    価格 ASC';

phpMyAdmin 内には既にこれを行うコードがいくつかあります。

4

7 に答える 7

27

私は同じ問題を抱えていて、フォーマット/構文の強調表示を行うために軽量のPHPクラスを作成しました。

https://github.com/jdorn/sql-formatter

複雑なクエリ(副選択、結合など)で完全にテストしていませんが、一般的なケースではかなりうまく機能しているようです。

完全に正確な結果を得るには、phpMyAdminが使用するような完全なSQLパーサーが本当に必要ですが、それは多くのファイルに分散された10,000行以上のコードを使用し、単純なデバッグにはおそらくやり過ぎです。

于 2012-04-30T07:19:33.827 に答える
11
function getFormattedSQL($sql_raw)
{
 if( empty($sql_raw) || !is_string($sql_raw) )
 {
  return false;
 }

 $sql_reserved_all = array (
     'ACCESSIBLE', 'ACTION', 'ADD', 'AFTER', 'AGAINST', 'AGGREGATE', 'ALGORITHM', 'ALL', 'ALTER', 'ANALYSE', 'ANALYZE', 'AND', 'AS', 'ASC',
     'AUTOCOMMIT', 'AUTO_INCREMENT', 'AVG_ROW_LENGTH', 'BACKUP', 'BEGIN', 'BETWEEN', 'BINLOG', 'BOTH', 'BY', 'CASCADE', 'CASE', 'CHANGE', 'CHANGED',
     'CHARSET', 'CHECK', 'CHECKSUM', 'COLLATE', 'COLLATION', 'COLUMN', 'COLUMNS', 'COMMENT', 'COMMIT', 'COMMITTED', 'COMPRESSED', 'CONCURRENT', 
     'CONSTRAINT', 'CONTAINS', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_TIMESTAMP', 'DATABASE', 'DATABASES', 'DAY', 'DAY_HOUR', 'DAY_MINUTE', 
     'DAY_SECOND', 'DEFINER', 'DELAYED', 'DELAY_KEY_WRITE', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV',
     'DO', 'DROP', 'DUMPFILE', 'DUPLICATE', 'DYNAMIC', 'ELSE', 'ENCLOSED', 'END', 'ENGINE', 'ENGINES', 'ESCAPE', 'ESCAPED', 'EVENTS', 'EXECUTE',
     'EXISTS', 'EXPLAIN', 'EXTENDED', 'FAST', 'FIELDS', 'FILE', 'FIRST', 'FIXED', 'FLUSH', 'FOR', 'FORCE', 'FOREIGN', 'FROM', 'FULL', 'FULLTEXT',
     'FUNCTION', 'GEMINI', 'GEMINI_SPIN_RETRIES', 'GLOBAL', 'GRANT', 'GRANTS', 'GROUP', 'HAVING', 'HEAP', 'HIGH_PRIORITY', 'HOSTS', 'HOUR', 'HOUR_MINUTE',
     'HOUR_SECOND', 'IDENTIFIED', 'IF', 'IGNORE', 'IN', 'INDEX', 'INDEXES', 'INFILE', 'INNER', 'INSERT', 'INSERT_ID', 'INSERT_METHOD', 'INTERVAL',
     'INTO', 'INVOKER', 'IS', 'ISOLATION', 'JOIN', 'KEY', 'KEYS', 'KILL', 'LAST_INSERT_ID', 'LEADING', 'LEFT', 'LEVEL', 'LIKE', 'LIMIT', 'LINEAR',               
     'LINES', 'LOAD', 'LOCAL', 'LOCK', 'LOCKS', 'LOGS', 'LOW_PRIORITY', 'MARIA', 'MASTER', 'MASTER_CONNECT_RETRY', 'MASTER_HOST', 'MASTER_LOG_FILE',
     'MASTER_LOG_POS', 'MASTER_PASSWORD', 'MASTER_PORT', 'MASTER_USER', 'MATCH', 'MAX_CONNECTIONS_PER_HOUR', 'MAX_QUERIES_PER_HOUR',
     'MAX_ROWS', 'MAX_UPDATES_PER_HOUR', 'MAX_USER_CONNECTIONS', 'MEDIUM', 'MERGE', 'MINUTE', 'MINUTE_SECOND', 'MIN_ROWS', 'MODE', 'MODIFY',
     'MONTH', 'MRG_MYISAM', 'MYISAM', 'NAMES', 'NATURAL', 'NOT', 'NULL', 'OFFSET', 'ON', 'OPEN', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', 'OR',
     'ORDER', 'OUTER', 'OUTFILE', 'PACK_KEYS', 'PAGE', 'PARTIAL', 'PARTITION', 'PARTITIONS', 'PASSWORD', 'PRIMARY', 'PRIVILEGES', 'PROCEDURE',
     'PROCESS', 'PROCESSLIST', 'PURGE', 'QUICK', 'RAID0', 'RAID_CHUNKS', 'RAID_CHUNKSIZE', 'RAID_TYPE', 'RANGE', 'READ', 'READ_ONLY',            
     'READ_WRITE', 'REFERENCES', 'REGEXP', 'RELOAD', 'RENAME', 'REPAIR', 'REPEATABLE', 'REPLACE', 'REPLICATION', 'RESET', 'RESTORE', 'RESTRICT',
     'RETURN', 'RETURNS', 'REVOKE', 'RIGHT', 'RLIKE', 'ROLLBACK', 'ROW', 'ROWS', 'ROW_FORMAT', 'SECOND', 'SECURITY', 'SELECT', 'SEPARATOR',
     'SERIALIZABLE', 'SESSION', 'SET', 'SHARE', 'SHOW', 'SHUTDOWN', 'SLAVE', 'SONAME', 'SOUNDS', 'SQL', 'SQL_AUTO_IS_NULL', 'SQL_BIG_RESULT',
     'SQL_BIG_SELECTS', 'SQL_BIG_TABLES', 'SQL_BUFFER_RESULT', 'SQL_CACHE', 'SQL_CALC_FOUND_ROWS', 'SQL_LOG_BIN', 'SQL_LOG_OFF',
     'SQL_LOG_UPDATE', 'SQL_LOW_PRIORITY_UPDATES', 'SQL_MAX_JOIN_SIZE', 'SQL_NO_CACHE', 'SQL_QUOTE_SHOW_CREATE', 'SQL_SAFE_UPDATES',
     'SQL_SELECT_LIMIT', 'SQL_SLAVE_SKIP_COUNTER', 'SQL_SMALL_RESULT', 'SQL_WARNINGS', 'START', 'STARTING', 'STATUS', 'STOP', 'STORAGE',
     'STRAIGHT_JOIN', 'STRING', 'STRIPED', 'SUPER', 'TABLE', 'TABLES', 'TEMPORARY', 'TERMINATED', 'THEN', 'TO', 'TRAILING', 'TRANSACTIONAL',    
     'TRUNCATE', 'TYPE', 'TYPES', 'UNCOMMITTED', 'UNION', 'UNIQUE', 'UNLOCK', 'UPDATE', 'USAGE', 'USE', 'USING', 'VALUES', 'VARIABLES',
     'VIEW', 'WHEN', 'WHERE', 'WITH', 'WORK', 'WRITE', 'XOR', 'YEAR_MONTH'
 );

 $sql_skip_reserved_words = array('AS', 'ON', 'USING');
 $sql_special_reserved_words = array('(', ')');

 $sql_raw = str_replace("\n", " ", $sql_raw);

 $sql_formatted = "";

 $prev_word = "";
 $word = "";

 for( $i=0, $j = strlen($sql_raw); $i < $j; $i++ )
 {
  $word .= $sql_raw[$i];

  $word_trimmed = trim($word);

  if($sql_raw[$i] == " " || in_array($sql_raw[$i], $sql_special_reserved_words))
  {
   $word_trimmed = trim($word);

   $trimmed_special = false;

   if( in_array($sql_raw[$i], $sql_special_reserved_words) )
   {
    $word_trimmed = substr($word_trimmed, 0, -1);
    $trimmed_special = true;
   }

   $word_trimmed = strtoupper($word_trimmed);

   if( in_array($word_trimmed, $sql_reserved_all) && !in_array($word_trimmed, $sql_skip_reserved_words) )
   {
    if(in_array($prev_word, $sql_reserved_all))
    {
     $sql_formatted .= '<b>'.strtoupper(trim($word)).'</b>'.'&nbsp;';
    }
    else
    {
     $sql_formatted .= '<br/>&nbsp;';
     $sql_formatted .= '<b>'.strtoupper(trim($word)).'</b>'.'&nbsp;';
    }

    $prev_word = $word_trimmed;
    $word = "";
   }
   else
   {
    $sql_formatted .= trim($word).'&nbsp;';

    $prev_word = $word_trimmed;
    $word = "";
   }
  }
 }

 $sql_formatted .= trim($word);

 return $sql_formatted;
}
于 2010-10-13T13:24:41.543 に答える
6

phpMyAdmin の使用は非常に簡単です。

require 'libraries/common.inc.php';

$sql= "select * from test";
$parsed_sql = PMA_SQP_parse($sql);    
echo PMA_SQP_formatHtml($parsed_sql);

スタイルシートを追加して、構文の強調表示を有効にします。sqlparserのドキュメントを少し読むと、さまざまな書式設定タイプの他の関数が見つかります。

唯一のことは、phpMyAdmin は SQL 解析のみを使用するにはやや大きいため、他のすべての機能を削除することをお勧めします...

于 2010-01-16T20:46:00.303 に答える
1

このようなものが機能します - 解析したい他の SQL キーワードを追加します。

function sql_format($query) {
  $keywords = array("select", "from", "where", "order by", "group by", "insert into", "update");
  foreach ($keywords as $keyword) {
    if (preg_match("/($keyword *)/i", $query, $matches)) {
      $query = str_replace($matches[1], "\n" . strtoupper($matches[1]) . "\n  ", $query);
    }
  }
  return $query;
}
于 2010-01-16T20:27:47.910 に答える
1

PECL などでこれを行う自由に利用できるコードはないと思います。これは非常にきちんとした小さなユーティリティであるため、残念です。(ただし、かなり限られた用途に限られます。)

そのため、あなた自身の質問に答えています - phpMyAdmin はおそらく最初の寄港地として適しています。

于 2010-01-16T20:01:00.687 に答える
1

これはあなたが望むものかもしれません: http://www.orczhou.com/sqlparser/ PHP SQL フォーマット

于 2011-01-21T05:15:05.583 に答える