2011-11-08 32 views
1

我想構建一個PHP腳本來驗證SQL查詢,但不會執行它。它不僅應該驗證語法,還應該在可能的情況下讓您知道查詢是否可以根據查詢中的命令執行。這裏是我想要做的事情的僞代碼:有沒有辦法讓PHP驗證SQL語法而不執行它?

<?php 
//connect user 
//connect to database 
//v_query = $_GET['usrinput']; 
if(validate v_query == true){ 
echo "This query can be executed"; 
} 
else{ 
echo "This query can't be executed because the table does not exist."; 
} 

//disconnect 
?> 

就像這樣。我希望它在不執行它的情況下模擬查詢。這就是我想要的,我無法在此找到任何東西。

爲什麼我們不希望執行查詢的一個例子是查詢是否向數據庫添加了某些內容。我們只是希望它在不修改數據庫的情況下進行模擬。

任何鏈接或例子將不勝感激!

+3

我很好奇的用例是在這裏。如果查詢無效,無論如何SQL都會返回一個錯誤......實際上,通過在腳本中執行的唯一方法是網絡連接時間。但是你在PHP解析查詢時產生的開銷中忽略了這種好處。 (DB服務器可以比PHP快得多解析它)。所有這些都說,你爲什麼需要這個? –

+0

您想要驗證哪種SQL語法? –

+0

嗨馬特,感謝您花一點時間回顧一下我的問題。我正在編寫一個將在查詢周圍生成PHP腳本的應用程序。當用戶編寫查詢時,他或她想檢查查詢是否有效,確定該行是否存在,當然還有語法,但不一定執行查詢。我們不希望查詢被執行的一個例子是如果查詢向數據庫添加了某些東西。我們只是希望它在不修改數據庫的情況下進行模擬。 –

回答

2

您可以嘗試以下庫:http://code.google.com/p/php-sql-parser/。我還沒有使用它,所以我不能保證它,但代碼看起來像它將能夠區分有效和無效的SQL。

如果您的SQL變體允許使用另一種選擇,則可以使用事務。一個事務將允許你執行SQL,然後在取消它之後撤消已經完成的任何損害。我想我寧願選擇1。

+0

我碰到'SET NOEXEC ON'聽起來有點兒我在找。讓我對它做更多的研究。 –

1

您不能僅僅解析和驗證SQL,因爲您需要檢查表的存在,JOIN的有效性等。執行完整集成測試的唯一方法是實際運行查詢。你可以把它包裝在一個事務中然後回滾。但是,糟糕的設計或惡意查詢仍然可能會導致服務器癱瘓或破壞數據。

+0

我遇到'SET NOEXEC ON'聽起來有點兒我在找。讓我對它做更多的研究。 –

1

從MySQL 5.6.3上,你可以使用EXPLAIN對於大多數查詢

我做這個和它的作品可愛:

function checkMySqlSyntax($mysqli, $query) { 
    if (trim($query)) { 
     // Remove comments # comment ; or # comment newline 
     // Remove SET @var=val; 
     // Remove empty statements 
     // Remove last ; 
     // Put EXPLAIN in front of every MySQL statement (separated by ;) 
     $query = "EXPLAIN " . 
       preg_replace(Array("/#[^\n\r;]*([\n\r;]|$)/", 
           "/[Ss][Ee][Tt]\s+\@[A-Za-z0-9_]+\s*=\s*[^;]+(;|$)/", 
           "/;\s*;/", 
           "/;\s*$/", 
           "/;/"), 
         Array("","", ";","", "; EXPLAIN "), $query) ; 

     foreach(explode(';', $query) as $q) { 
     $result = $mysqli->query($q) ; 
     $err = !$result ? $mysqli->error : false ; 
     if (! is_object($result) && ! $err) $err = "Unknown SQL error"; 
     if ($err) return $err ; 
     } 
     return false ; 
    } 
} 

它西港島線返回false,如果去查詢是OK(多;分隔的語句允許的),或者是一個錯誤消息,說明如果有其他語法或其他MySQL(比如不存在的表或列),就會報錯。

已知的錯誤:

  • 用含有#或字符串文字查詢;將失敗
  • 與linenumbers MySQL錯誤:linenumbers大多不匹配。
  • 不超過SELECT,UPDATE其他MySQL語句的工作,REPLACE,INSERT,DELETE
相關問題