2008-11-05 14 views
11

我曾經使用標準的mysql_connect(),mysql_query()等聲明來從PHP中做MySQL的東西。最近我一直在使用美妙的MDB2課程。與此同時,我使用了準備好的語句,所以我不必擔心會逃避我的輸入和SQL注入攻擊。MySQL中非空列中的空字符串?

但是,我遇到了一個問題。我有一個包含幾個VARCHAR列的表,它們被指定爲非null(即不允許NULL值)。使用舊版本的MySQL PHP命令,我可以做這樣的事情,沒有任何問題:

INSERT INTO mytable SET somevarchar = ''; 

但是現在,如果我有這樣的查詢:

INSERT INTO mytable SET somevarchar = ?; 

然後在PHP我有:

$value = ""; 
$prepared = $db->prepare($query, array('text')); 
$result = $prepared->execute($value); 

這將引發錯誤 「null value violates not-null constraint

作爲臨時解決辦法,I C heck如果$value爲空,並將其更改爲" "(單個空格),但這是一個可怕的黑客攻擊,可能會導致其他問題。

我該如何插入空字符串與準備語句,沒有它試圖插入NULL?

編輯:它是一個項目太大,通過我的整個代碼庫,發現無處不在,使用空字符串「」,並改爲使用NULL。我需要知道的是爲什麼標準MySQL查詢將「」和NULL作爲兩個單獨的東西(我認爲是正確的)對待,但準備語句將「」轉換爲NULL。

請注意,「」和NULL是而不是是同樣的事情。例如,SELECT NULL = "";將返回NULL而不是您所期望的1

+1

如果插入「」,這是basicly空,爲什麼不改變在該領域數據庫允許爲空。 – UnkwnTech 2008-11-05 20:09:04

+6

它的「基本上爲零」的方式與0基本上是錯誤的一樣。他們很相似,但實際上完全不同。 – nickf 2008-11-05 20:11:30

+1

NULL表示「沒有值」不是,「空字符串」 – warren 2008-11-05 20:12:30

回答

11

這聽起來像一個問題MDB2 API摸索PHP的鴨子打字語義。由於PHP中的空字符串等於NULL,因此MDB2可能會對其進行錯誤處理。理想的解決方案是在其API中找到解決方法,但我不太熟悉它。

但是,您應該考慮的一件事是,SQL中的空字符串不是NULL值。你可以將它們插入到行宣佈「NOT NULL」就好了:

mysql> CREATE TABLE tbl(row CHAR(128) NOT NULL); 
Query OK, 0 rows affected (0.05 sec) 

mysql> INSERT INTO tbl VALUES('not empty'), (''); 
Query OK, 2 rows affected (0.02 sec) 
Records: 2 Duplicates: 0 Warnings: 0 

mysql> SELECT row, row IS NULL FROM tbl; 
+-----------+-------------+ 
| row  | row IS NULL | 
+-----------+-------------+ 
| not empty |   0 | 
|   |   0 | 
+-----------+-------------+ 
2 rows in set (0.00 sec) 

mysql> INSERT INTO tbl VALUES(NULL); 
ERROR 1048 (23000): Column 'row' cannot be null 

如果您無法找到(或執行)的MDB2 API的解決辦法,一個hackish的解決方案(雖然一個比你稍微好一點「再目前使用)可能是定義爲user variable空字符串 -

SET @EMPTY_STRING = ""; 
UPDATE tbl SET [email protected]_STRING; 

最後,如果你需要用空字符串在INSERT語句,但發現自己無法,對於字符串類型的默認值在MySQL中是一個空字符串。所以你可以簡單地從INSERT語句中省略列,並且它會自動設置爲空字符串(如果該列有NOT NULL約束)。

0

不是一組空的引號,""是否做到這一點?

-1

我很困惑。它看起來像你使用的mysqli OO(從標籤和作風),但語法比manual上php.net不同,它說要做到這一點,而不是:

$query = "INSERT INTO mytable SET somevarchar = ?"; 
$value = ""; 
$prepared = $db->prepare($query); 
$prepared->bind_param("s", $value); 
$result = $prepared->execute(); 
17

感謝一些答案,我意識到這個問題可能在MDB2 API中,而不是在PHP或MYSQL命令本身。果然,我發現這個在MDB2 FAQ:

  • 爲什麼空字符串結束了在數據庫中的NULL?爲什麼在NOT NULL文本字段中不允許使用NULL 儘管默認值是「」?
    • 問題是,對於某些RDBMS(最值得注意的是Oracle),一個空的 字符串是NULL。因此MDB2 爲 提供了一個可移植性選項,以便在所有的012BBD上執行相同的行爲。
    • 既然所有可移植性選項是默認啓用的,你將有 禁用,如果你不 希望有這種行爲的功能: $ mdb2->的SetOption(「便攜」, MDB2_PORTABILITY_ALL^ MDB2_PORTABILITY_EMPTY_TO_NULL);

謝謝大家誰提供周到的答案。

2

我意識到這個問題已經得到了很多答案並退休了,但是我在找到類似情況的答案時發現了這個問題,我無法拒絕在戒指中投擲我的帽子。

不知道NULL /「」列與什麼有關,我無法知道空字符串的真正意義。空字符串是否意味着自己的意思(比如,如果我說服法官讓我把我的名字改爲沒有任何意思,如果我的姓名出現在我的駕駛執照中爲NULL,我真的很惱火。我的名字就是!

然而,空字符串(或空白,或者沒有任何東西是SOMETHING,不僅僅是缺少任何東西(如NULL))也可能僅僅意味着「NOT NULL」或「Nothing,但仍然不是NULL」。去另一個方向,並建議NULL值的缺失使得它甚至比Null更少,因爲至少Null有你可以大聲說出的名字!

我的觀點是,如果空字符串是一些數據的直接表示(如名稱,或者我喜歡在我的電話號碼之間插入的數字等),那麼您的選擇要麼爭辯,要麼直到您對空字符串的合法使用感到痛心,或者使用表示空值的字符串不是NULL(例如,ASCII控制字符或某個unicode等價物,某種正則表達式值,或者更糟糕的是,任意值但完全沒有使用的令牌,如:◘

如果空單元格真的只意味着NOT NULL,那麼您可以考慮用其他方式來表達它。一個很不明顯的方式是短語「Not NULL」。一個預感,NULL意味着像「根本不屬於這個羣體」,而空字符串意味着一些就像「這傢伙很酷,他還沒有得到他的幫派紋身」。在這種情況下,我會爲這種情況提出一個術語/名稱/想法,例如「默認」或「菜鳥」或「待定」。

現在,如果出於某種瘋狂的機會,您實際上想要空字符串來表示那些甚至不值得NULL的字符串,再次爲此提供一個更重要的符號,例如「-1」或「SUPERNULL」或「UGLIES」。

在印度的種姓製度中,最低的種姓是舒德拉:農民和勞工。在這個種姓的下面是達利特:「不可馴服者」。它們不被視爲較低等級,因爲將它們設定爲最低等級將被認爲是整個系統的污染。

所以,不要說我瘋狂的思維空字符串可能會比NULL更惡劣!

'直到下一次。

1

我找到了解決方案!

MDB2將空字符串轉換爲NULL,因爲默認情況下打開了可移植性選項MDB2_PORTABILITY_EMPTY_TO_NULL(感謝Oracle認爲空字符串爲空)。

開關,當您連接到數據庫,這個選項關閉:

$options = array(
    'portability' => MDB2_PORTABILITY_ALL^MDB2_PORTABILITY_EMPTY_TO_NULL 
); 
$res= & MDB2::connect("mysql://user:[email protected]/dbase", $options); 
1

雖然0和空字符串是變量NULL是沒有數據的。相信我,這是一個更容易查詢寫

SELECT * from table where mything IS NULL不是試圖查詢空字符串:/