2008-11-05 44 views
11

Tôi đã từng sử dụng các câu lệnh mysql_connect(), mysql_query(), vv chuẩn để thực hiện các công cụ MySQL từ PHP. Gần đây tôi đã chuyển sang sử dụng lớp MDB2 tuyệt vời. Cùng với nó, tôi đang sử dụng các câu lệnh chuẩn bị, vì vậy tôi không phải lo lắng về việc thoát khỏi các cuộc tấn công đầu vào và SQL injection của mình.Chuỗi rỗng trong cột không rỗng trong MySQL?

Tuy nhiên, có một vấn đề mà tôi đang gặp phải. Tôi có một bảng với một vài cột VARCHAR, được chỉ định là không null (có nghĩa là, không cho phép các giá trị NULL). Sử dụng các lệnh MySQL PHP cũ, tôi có thể làm những việc như thế này mà không cần bất kỳ vấn đề:

INSERT INTO mytable SET somevarchar = ''; 

Bây giờ, tuy nhiên, nếu tôi có một truy vấn như:

INSERT INTO mytable SET somevarchar = ?; 

Và sau đó trong PHP tôi có:

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

này sẽ ném lỗi "null value violates not-null constraint"

là một workaround tạm thời, tôi c heck nếu $value trống và thay đổi thành " " (một không gian), nhưng đó là một hack khủng khiếp và có thể gây ra các vấn đề khác.

Làm cách nào để chèn các chuỗi trống với các câu lệnh đã chuẩn bị sẵn sàng, mà không cần cố gắng để chèn một NULL?

CHỈNH SỬA: Quá lớn của một dự án đi qua toàn bộ codebase của tôi, tìm ở mọi nơi sử dụng chuỗi trống "" và thay đổi nó để sử dụng NULL thay thế. Những gì tôi cần biết là tại sao các truy vấn MySQL chuẩn xử lý "" và NULL là hai thứ riêng biệt (như tôi nghĩ là đúng), nhưng các câu lệnh chuẩn bị chuyển đổi "" thành NULL.

Lưu ý rằng "" và NULL là không phải là điều tương tự. Ví dụ: SELECT NULL = ""; trả về NULL thay vì 1 như bạn mong muốn.

+1

Nếu bạn đang chèn "", mà là cơ bản null, tại sao không thay đổi lĩnh vực này trong db để cho phép null. – UnkwnTech

+6

nó "về cơ bản là vô giá trị" trong cùng một cách mà 0 là "về cơ bản" sai. chúng tương tự nhưng thực sự khá khác nhau. – nickf

+1

NULL có nghĩa là "không có giá trị" không, "chuỗi rỗng" – warren

Trả lời

11

này nghe có vẻ như một vấn đề với API MDB2 dò dẫm ngữ nghĩa gõ vịt của PHP. Bởi vì chuỗi rỗng trong PHP tương đương với NULL, MDB2 có lẽ là xử lý sai nó như vậy. Giải pháp lý tưởng sẽ là tìm giải pháp cho nó trong API của nó, nhưng tôi không quá quen thuộc với nó.

Một điều mà bạn nên xem xét, tuy nhiên, là một chuỗi rỗng trong SQL không phải là giá trị NULL.Bạn có thể chèn chúng vào hàng tuyên bố 'NOT NULL' tốt:

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 

Nếu bạn không thể tìm thấy (hoặc thực hiện) một cách giải quyết trong API MDB2, một giải pháp hackish (mặc dù tốt hơn một chút so với cái bạn đang hiện đang sử dụng) có thể xác định một user variable cho chuỗi rỗng -

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

Cuối cùng, nếu bạn cần phải sử dụng chuỗi rỗng trong một tuyên bố INSERT nhưng thấy mình không có khả năng, giá trị mặc định cho các loại chuỗi trong MySQL là một chuỗi rỗng. Vì vậy, bạn có thể chỉ cần bỏ qua cột từ câu lệnh INSERT và nó sẽ tự động được đặt thành chuỗi rỗng (miễn là cột có ràng buộc NOT NULL).

+0

Đây là nó, tôi không nghĩ rằng MDB2 chính nó có thể là thủ phạm. Cảm ơn. – davr

0

Không có bộ dấu ngoặc kép nào, "" làm điều đó?

+0

Không, "" và NULL là những thứ khác nhau và hoạt động khác nhau trong hầu hết các cơ sở dữ liệu. – davr

+0

@davr - đó chính xác là lý do tôi nói để làm điều đó - anh ấy đang cố gắng lấy giá trị NOT NULL vào db, dấu ngoặc đơn trống là – warren

-1

Tôi đang bối rối. Dường như bạn đang sử dụng mysqli OO (từ các thẻ và phong cách), nhưng cú pháp là khác nhau hơn so với manual trên php.net, mà nói để làm điều này thay vì:

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

Tôi đang sử dụng MDB2, sử dụng mysqli trong nội bộ. – davr

17

Nhờ một số câu trả lời, tôi nhận ra rằng sự cố có thể nằm trong API MDB2, chứ không phải trong chính các lệnh PHP hoặc MYSQL. Chắc chắn, tôi đã tìm thấy điều này trong Câu hỏi thường gặp về MDB2:

  • Tại sao chuỗi rỗng kết thúc bằng NULL trong cơ sở dữ liệu? Tại sao tôi nhận được một NULL không được phép trong trường văn bản NOT NULL dù giá trị mặc định là ""?
    • Vấn đề là đối với một số RDBMS (đáng chú ý nhất là Oracle) một chuỗi rỗng là NULL. Do đó MDB2 cung cấp tùy chọn di động để thực thi cùng một hành vi trên tất cả RDBMS.
    • Vì tất cả các tùy chọn di động được kích hoạt theo mặc định, bạn sẽ có để vô hiệu hóa tính năng này nếu bạn không muốn có hành vi này: $ mdb2-> setOption ('di động', MDB2_PORTABILITY_ALL^​​ MDB2_PORTABILITY_EMPTY_TO_NULL);

Nhờ tất cả những ai cung cấp câu trả lời chu đáo.

2

Tôi nhận ra câu hỏi này được trả lời khá nhiều và đã nghỉ hưu, nhưng tôi đã tìm thấy câu trả lời cho một tình huống tương tự và tôi không thể cưỡng lại việc ném chiếc mũ của mình trong vòng.

Không biết cột NULL/"" có liên quan đến gì, tôi không thể biết được ý nghĩa thực sự của một chuỗi trống. Có chuỗi rỗng có nghĩa là một cái gì đó cho chính nó (như, nếu tôi thuyết phục một thẩm phán để cho tôi thay đổi tên của tôi chỉ đơn giản là không có gì, tôi sẽ thực sự bị kích thích nếu tên của tôi xuất hiện trên Giấy phép lái xe của tôi như NULL Tên của tôi sẽ là

Tuy nhiên, các chuỗi rỗng (hoặc trống, hoặc không có gì đó là SOMETHING, không chỉ đơn giản là thiếu bất cứ điều gì (như NULL)) cũng có thể chỉ đơn giản chỉ có nghĩa là "NOT NULL" hoặc "Không có gì, nhưng vẫn không Null". đi theo hướng khác và gợi ý rằng sự vắng mặt của giá trị NULL làm cho nó thậm chí LESS một cái gì đó hơn Null, cuz ít nhất Null có một tên bạn có thể nói to!

Quan điểm của tôi là, nếu chuỗi rỗng là biểu diễn trực tiếp của một số dữ liệu (như tên hoặc thứ tôi muốn chèn vào giữa các số trong số điện thoại của tôi, v.v.), thì các tùy chọn của bạn sẽ tranh luận cho đến bạn đang đau vì sử dụng hợp pháp chuỗi rỗng hoặc sử dụng thứ gì đó đại diện cho một chuỗi rỗng không phải là NULL (Giống như một ký tự điều khiển ASCII hoặc một số tương đương unicode, giá trị regex của một số loại hoặc thậm chí tệ hơn, tùy ý nhưng mã thông báo hoàn toàn không được sử dụng, như: ◘

Nếu ô trống thực sự chỉ có nghĩa là NOT NULL, thì bạn có thể nghĩ ra một số cách khác để diễn đạt nó một cách ngớ ngẩn và rõ ràng là cụm từ "Không NULL". một linh cảm mà NULL có nghĩa là một cái gì đó như "Không phải là một phần của nhóm này ở tất cả" trong khi chuỗi rỗng có nghĩa là someth ing như "anh chàng này là mát mẻ, anh ta vẫn chưa nhận được hình xăm băng đảng của mình chưa". Trong trường hợp đó tôi sẽ đưa ra một thuật ngữ/tên/ý tưởng cho tình huống này, như "mặc định" hoặc "tân binh" hoặc "Đang chờ xử lý". Bây giờ, nếu một số cơ hội điên rồ bạn thực sự muốn chuỗi rỗng để đại diện cho cái mà thậm chí không xứng đáng với NULL, một lần nữa, hãy đưa ra một biểu tượng quan trọng hơn cho điều đó, chẳng hạn như "-1" hoặc "SUPERNULL" hoặc "UGLIES".

Trong hệ thống Caste Ấn Độ, Caste thấp nhất là Shudra: Nông dân và người lao động. Bên dưới đẳng cấp này là Dalit: "The Untouchables". Họ không được coi là một đẳng cấp thấp hơn, bởi vì thiết lập chúng như là đẳng cấp thấp nhất sẽ được coi là một ô nhiễm của toàn bộ hệ thống.

Vì vậy, đừng gọi tôi là điên vì nghĩ chuỗi rỗng có thể là WORSE hơn NULL!

'Cho đến lần sau.

1

Tôi đã tìm ra giải pháp!

MDB2 chuyển đổi chuỗi rỗng thành NULL vì tùy chọn khả năng di động MDB2_PORTABILITY_EMPTY_TO_NULL được bật theo mặc định (nhờ Oracle xem chuỗi trống rỗng).

Chuyển tùy chọn này tắt khi bạn kết nối với cơ sở dữ liệu:

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

uhm ... Tôi đã viết câu trả lời chính xác này hơn một năm trước. – davr

+0

Rất tiếc :-) Tôi không nhận thấy điều đó. – ahhon

1

Trong khi 0 và trống rỗng chuỗi là các biến NULL là sự vắng mặt của dữ liệu. Và tôi tin tưởng, đó là dễ dàng hơn nhiều để viết một truy vấn để

SELECT * from table where mything IS NULL hơn để cố gắng truy vấn cho các chuỗi rỗng:/