2014-08-29 65 views
0

我在Windows 7上運行PHP5.3和SQL Server 2014的IIS 6.1。我的數據庫基於我的iTunes播放列表。我目前正在處理的劇本從表格中獲得樂隊的名稱,然後返回表格中每個專輯的表格,顯示每個專輯的名稱和年份,然後顯示每首歌曲的曲目編號,名稱和長度那張專輯。它適用於我的大部分專輯,但存在三個問題:PHP/SQLSRV:3查詢問題

  1. 非拉丁字符不顯示。我有幾種不同語言的音樂,並且我可以在SQL Server中使用Unicode字符進行查詢,但是當我嘗試在網絡上返回這些結果時,所有非拉丁字符都顯示爲問號。我見過的這個問題的答案並沒有解決我的問題(例如,添加一個標題和meta標籤來設置頁面爲UTF-8)。

  2. 一個特殊的專輯(國王Crimson的小說中的Larks'Tongues)會激化查詢,大概是因爲專輯標題中的單引號。奇怪的是,專輯名稱顯示得很好,但不是該專輯的曲目。其他歌曲和名單中的單引號專輯不會導致問題,只有這個特定的專輯/歌曲。我已經嘗試了所有可以想到的單引號轉義組合,而且它們都會導致查詢失敗。我已經開啓和關閉了魔法報價,但沒有任何結果。正如下面寫的,該查詢返回此錯誤:

    Array ([0] => Array ([0] => 42000 [SQLSTATE] => 42000 [1] => 102 
    [code] => 102 [2] =>   [Microsoft][SQL Server Native Client 11.0] 
    [SQL Server]Incorrect syntax near 'Tongues'. [message] => [Microsoft] 
    [SQL Server Native Client 11.0][SQL Server]Incorrect syntax near 'Tongues'.) 
    [1] => Array ([0] => 42000 [SQLSTATE] => 42000 [1] => 105 [code] => 105 
    [2] => [Microsoft][SQL Server Native Client 11.0][SQL Server] 
    Unclosed quotation mark after the character string ' ORDER BY TrackNumber'.  
    [message] => [Microsoft][SQL Server Native Client 11.0][SQL Server] 
    Unclosed quotation mark after the character string ' ORDER BY TrackNumber'.)) 
    
  3. 我無法弄清楚如何在查詢中包含通配符。例如,如果我搜索「艾莉森克勞斯」,我只能得到艾莉森自己的結果。如果我想搜索歌曲,其中Alison是多位藝術家之一(例如,Alison Krauss & Union Station),我需要爲查詢添加通配符,但我無法弄清楚如何做到這一點,無論是通過將其添加到傳遞到查詢中的變量或查詢本身中。

下面是代碼:

header('Content-type: text/html; charset=UTF-8'); 

    require_once ('connect.php'); 

    echo '<table align = center cellpadding = 2 cellspacing = 2>'; 

    $band = stripslashes($_REQUEST['band']); 

    $albumqry = "SELECT AlbumName, AlbumYear FROM vw_AlbumTracks WHERE ArtistName LIKE '$band'   
    GROUP BY AlbumName, AlbumYear ORDER BY AlbumYear"; 

    $ayqry = SQLSRV_QUERY($conn, $albumqry); 
    if($ayqry === false) 
    { 
     echo "Error in executing query.</br>"; 
     die(print_r(sqlsrv_errors(), true)); 
    } 

    while ($record = SQLSRV_FETCH_ARRAY ($ayqry)) { 

    $album = $record['AlbumName']; 

    echo '<tr><td colspan=3><b>' . $album . ' (' . $record['AlbumYear'] . ')</b></td></tr>'; 

    $query = "SELECT TrackNumber, SongName, SongLength FROM vw_AlbumTracks WHERE ArtistName     
    LIKE N'$band' AND AlbumName LIKE N'$album' ORDER BY TrackNumber"; 

    $stmt = sqlsrv_query($conn, $query); 
    if($stmt === false) 
    { 
     echo "Error in executing query.</br>"; 
     die(print_r(sqlsrv_errors(), true)); 
    } 

    while($track = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { 
    echo '<tr><td width = 5>' . $track['TrackNumber'] . '.</td> 
    <td width = 300>' . $track[stripslashes('SongName')] . '</td> 
    <td style="text-align:right">' . $track['SongLength'] . '</right></td></tr>'; 

    } 

    echo '<tr></tr>'; 

    } 

    echo '</table>'; 

回答

0

解決兩個我自己的問題。

  1. 添加通配符:將通配符和N(用於輸入Unicode字符)添加到變量定義中。例如:

    $band = "N'" . stripslashes($_POST['band']) . "%'"; 
    $albumqry = "SELECT AlbumName, AlbumYear FROM vw_AlbumTracks WHERE ArtistName 
    LIKE $band GROUP BY AlbumName, AlbumYear ORDER BY AlbumYear"; 
    
  2. 逃逸在傳遞到SQL查詢的PHP單引號:使用str_replace函數結合和addslashes到第一逃離麻煩單引號,然後重新逸出它們的方式,SQL理解。

    $album = "N'" . str_replace("\'", "''", addslashes($record['AlbumName'])) . "'"; 
    

還是完全失去了對Unicode的事情,雖然。我加了echo $ band;在頁面上輸入윤하後,它會顯示N'윤하%',這正是它應該傳遞給SQL Server的內容,但是SQL Server Profiler中的跟蹤將查詢顯示爲

SELECT AlbumName, AlbumYear FROM vw_AlbumTracks 
    WHERE ArtistName LIKE N'윤하%' 
    GROUP BY AlbumName, AlbumYear ORDER BY AlbumYear 

因此,不管怎樣,Unicode從PHP到SQL Server的方式都變得亂七八糟,它們都能夠正確顯示它們。