香蕉成人伊视频在线观看|学生小视频国产区|yy女主播啪啪啪视频|麻豆传播媒体APP大全免费版官网|瑜伽牲交AV|国产欧美日韩在线天堂区|白浆精品国产91

返回列表 發帖
查看: 756|回復: 3

[求助] 使用原生DELET語句無空格時無法刪除數據的問題

1

主題

6

回帖

1

粉絲

初學乍練

貢獻
0 點
金幣
10 個
樓主
發表于 2026-1-16 10:43:04 |北京| 只看樓主 |倒序瀏覽 |閱讀模式

1. 問題:

我使用DELETE語句刪除數據的時候,如果引號內兩側不留空的時候,刪除就不會執行,比如,下面這樣就可以成功從數據庫中刪除: delpsqlf="DELETEFROMdatatable WHERE sid = sid";DB::query(delpsqlf); 而下面這樣,顯示已執行,但數據庫中的數據并未刪除,數據庫也無報錯: delpsqlf="DELETEFROMdatatable WHERE sid = sid";DB::query(delpsqlf);

2. 千問的回答:

針對上述問題,我將discuz_database.php發給千問,給的結果為:
通過分析您提供的PHP類代碼,我發現問題出在Discuz框架的SQL安全檢查機制上。讓我為您詳細解釋:
問題根源
問題主要出現在discuz_database_safecheck::checkquery()方法中,這個方法負責SQL語句的安全檢查。關鍵代碼如下:
$cmd = strtoupper(substr(trim($sql), 0, 3)); if(isset(self::$checkcmd[$cmd])) { $check = self::_do_query_safe($sql); }
這里self::$checkcmd定義為:
protected static $checkcmd = array('SEL'=>1, 'UPD'=>1, 'INS'=>1, 'REP'=>1, 'DEL'=>1);
具體分析
當SQL語句有前后空格時(" DELETE FROM table WHERE sid = sid"trim(sql)會移除前后空格,得到"DELETE FROM table WHERE sid = sid"substr(trim(sql), 0, 3)返回"DEL" "DEL"在checkcmdSQL"DELETEFROMtableWHEREsid=sid"): 同樣經過trim()處理,理論上應該得到相同結果 但在_do_query_safe()方法中,正則清理邏輯對格式高度敏感:
$clean = preg_replace("/[^a-z0-9_\-\(\)#\*\/\"]+/is", "", strtolower($clean));
這個復雜的清理邏輯可能因缺少空格而導致清理后的SQL字符串不包含"del"關鍵字 最終安全檢查失敗,但框架沒有拋出異常,而是靜默失敗

3. 智普的回答:

針對上述問題,我將discuz_database.php發給千問,給的結果為:
這個問題出在 DB::query 方法中提取 SQL 命令類型的邏輯上。
問題分析
當你在 SQL 語句字符串($delpsqlf)的開頭(引號內側)添加空格時,DB::query 中的代碼邏輯會導致返回值類型不一致,從而影響你的業務邏輯判斷(例如 if(DB::query(...)))。 請看 discuz_database 類中的 query 方法:
public static function query($sql, $arg = array(), $silent = false, $unbuffered = false) { // ... 前面的代碼省略 ... // 執行 SQL 查詢 $ret = self::$db->query($sql, $silent, $unbuffered); if (!$unbuffered && $ret) { // 【問題出在這里】 // 使用 strpos 查找第一個空格的位置來截取命令名稱(如 DELETE, SELECT 等) $cmd = trim(strtoupper(substr($sql, 0, strpos($sql, ' ')))); if ($cmd === 'SELECT') { // ... } elseif ($cmd === 'UPDATE' || $cmd === 'DELETE') { // 如果命令是 UPDATE 或 DELETE,將返回值替換為受影響的行數 $ret = self::$db->affected_rows(); } elseif ($cmd === 'INSERT') { $ret = self::$db->insert_id(); } } return $ret; }
為什么會有兩種結果?
情況一:語句前面有空格(" DELETE FROM ...") strpos(sql,′′)0substr(sql, 0, 0) 返回空字符串 ""。 cmdcmd 不等于 'DELETE',代碼跳過了 ret=self::db->affected_rows(); 這一步。 最終 DB::query 返回的是 MySQL 的結果對象(Resource/Object)。 在 PHP 中,非空的對象轉換為布爾值通常是 true。所以你的代碼認為“執行成功”。
情況二:語句前面沒有空格("DELETE FROM ...") strpos(sql,′′)DELETE6substr(sql, 0, 6) 返回 "DELETE"。 cmd"DELETE"elseif(cmd === 'UPDATE' || cmd===DELETE)ret 被賦值為 self::$db->affected_rows()(受影響的行數)。 關鍵點: 如果 SQL 實際上沒有刪除任何數據(例如 sid 不匹配,或者你使用了事務未提交),affected_rows() 返回 0。 你的代碼判斷 if(0) 結果為 false,所以你認為“執行失敗”或“未刪除”。
為什么數據庫里實際上沒被刪除?
既然情況一顯示“成功刪除”,情況二顯示“未刪除”,但你提到情況二“數據庫中的數據并未刪除”,這意味著 affected_rows 確實返回了 0。 這說明在兩種情況下,發給數據庫的 SQL 語句實際上可能都沒有匹配到數據(或者 $sid 在第二種情況下的值有問題)。但是:
javascript
我知道答案 回答被采納將會獲得1 貢獻 已有3人回答
回復

使用道具 舉報

50

主題

3408

回帖

11

粉絲

應用開發者

Discuz! 運維

貢獻
232 點
金幣
685 個
QQ
沙發
發表于 2026-1-16 11:03:06 |江蘇| 只看Ta
;P代碼都貼不好,這AI開發者真的是。。。
回復

使用道具 舉報

15

主題

3730

回帖

6

粉絲

應用開發者

貢獻
440 點
金幣
172 個
QQ
板凳
發表于 2026-1-16 11:30:53 |河南| 只看Ta
科站網 發表于 2026-1-16 11:03
;P代碼都貼不好,這AI開發者真的是。。。

拒絕為 ai開發者 提供任何幫助
回復

使用道具 舉報

5

主題

20

回帖

2

粉絲

初學乍練

貢獻
0 點
金幣
8 個
地板
發表于 2026-1-16 11:41:07 |河南| 只看Ta
你問gemini啊,國內的不行

3. 如何驗證和修復?

為了徹底解決這個問題,建議按以下步驟操作:

第一步:確認數據庫里的真實數據

不要只用肉眼看,使用 SQL 的長度函數來檢查數據庫里到底存了什么。
執行這個查詢(假設你要查 sid 為 '1001' 的那條):
SQL-- MySQL / PostgreSQL / SQLite SELECT sid, LENGTH(sid) as len FROM datatable WHERE sid LIKE '%1001%';
  • 如果顯示 sid1001,但 len6(而不是4),說明前后各有一個空格。
  • 這就是為什么你不留空格刪不掉,留了空格(剛好湊對了)才能刪掉的原因。

第二步:修復代碼(推薦使用 TRIM)

為了防止未來再出現這種“必須手動加空格才能刪”的玄學問題,建議在 SQL 中忽略空格,或者在代碼層清理數據。
方案 A:在 SQL 中強制忽略兩端空格(最穩妥) 無論數據庫里有沒有空格,都進行修剪后再比對:
SQL-- 將數據庫里的字段和傳入的值都去除空格進行比對 DELETE FROM datatable WHERE TRIM(sid) = TRIM('你的變量值');
方案 B:在插入數據時就清洗 這是治本的方法。在寫入數據庫(INSERT/UPDATE)之前,確保對變量進行了 trim() 處理(去除首尾空格)。

第三步:使用參數化查詢(Binding)

你目前使用的看起來像是字符串拼接(String Concatenation),這不僅容易出現空格拼接錯誤,還極易遭受 SQL 注入攻擊
建議改為參數化查詢(偽代碼示例):
C++// 錯誤寫法(拼接) query("DELETE FROM table WHERE sid = '" + sid + "'"); // 正確寫法(參數化綁定) // 這樣你就不用擔心引號、空格拼接的問題,數據庫庫函數會幫你處理 query.prepare("DELETE FROM table WHERE sid = ?"); query.bindValue(0, sid.trimmed()); // 傳入前去除空格 query.exec();

總結

你遇到的“不報錯但不刪除”,是因為**WHERE 條件沒有匹配到任何數據**。最直接的原因是你的數據庫中存儲的數據包含了首尾空格,導致精確匹配失敗。
下一步建議: 你可以先執行一句 SELECT sid FROM datatable WHERE sid LIKE '%...%' 看看那些刪不掉的數據長度是多少,確認是否包含空格。需要我幫你寫針對你特定數據庫類型的排查 SQL 嗎?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

  • 關注公眾號
  • 有償服務微信
  • 有償服務QQ

手機版|小黑屋|Discuz! 官方交流社區 ( 皖ICP備16010102號 |皖公網安備34010302002376號 )|網站地圖|star

GMT+8, 2026-5-31 05:31 , Processed in 0.061063 second(s), 11 queries , Redis On.

Powered by Discuz! X5.0 Licensed

© 2001-2026 Discuz! Team.

關燈 在本版發帖
有償服務QQ
有償服務微信
返回頂部
快速回復 返回頂部 返回列表