سؤال

اعتدت استخدام عبارات mysql_connect() وmysql_query() وغيرها للقيام بأشياء MySQL من PHP.لقد قمت مؤخرًا بالتبديل إلى استخدام فئة MDB2 الرائعة.بالإضافة إلى ذلك، أستخدم البيانات المعدة مسبقًا، لذلك لا داعي للقلق بشأن الهروب من هجمات الإدخال وحقن SQL.

ومع ذلك، هناك مشكلة واحدة أواجهها.لدي جدول يحتوي على عدد قليل من أعمدة VARCHAR، التي تم تحديدها على أنها غير فارغة (أي لا تسمح بالقيم الخالية).باستخدام أوامر 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"

كحل مؤقت، أتحقق مما إذا $value فارغة، وتغييره إلى " " (مسافة واحدة)، ولكن هذا اختراق فظيع وقد يسبب مشكلات أخرى.

كيف من المفترض أن أقوم بإدراج سلاسل فارغة مع عبارات معدة، دون أن أحاول بدلاً من ذلك إدراج قيمة فارغة؟

يحرر: إنه مشروع كبير جدًا بحيث لا يمكنني مراجعة قاعدة التعليمات البرمجية الخاصة بي بالكامل، والعثور على كل مكان يستخدم سلسلة فارغة "" وتغييره لاستخدام NULL بدلاً من ذلك.ما أحتاج إلى معرفته هو سبب تعامل استعلامات MySQL القياسية مع "" وNULL كشيئين منفصلين (كما أعتقد أن هذا صحيح)، لكن العبارات المعدة تحول "" إلى NULL.

لاحظ أن "" وNULL هما لا نفس الشيء.على سبيل المثال، SELECT NULL = ""; عائدات NULL بدلاً من 1 كما كنت تتوقع.

هل كانت مفيدة؟

المحلول

يبدو هذا وكأنه مشكلة في MDB2 API التي تتخبط في دلالات كتابة البط في PHP.نظرًا لأن السلسلة الفارغة في PHP تعادل NULL، فمن المحتمل أن MDB2 يسيء معاملتها على هذا النحو.سيكون الحل المثالي هو العثور على حل بديل له ضمن واجهة برمجة التطبيقات (API) الخاصة به، لكنني لست على دراية به بشكل مفرط.

هناك شيء واحد يجب عليك مراعاته، وهو أن السلسلة الفارغة في SQL ليست قيمة فارغة.يمكنك إدراجها في الصفوف التي تم الإعلان عنها بأنها "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، فقد يكون أحد الحلول المخترقة (رغم أنه أفضل قليلاً من الحل الذي تستخدمه حاليًا) هو تحديد متغير المستخدم للسلسلة الفارغة -

SET @EMPTY_STRING = "";
UPDATE tbl SET row=@EMPTY_STRING;

أخيرًا، إذا كنت بحاجة إلى استخدام السلسلة الفارغة في عبارة INSERT ولكنك تجد نفسك غير قادر على ذلك، فإن القيمة الافتراضية لأنواع السلاسل في MySQL هي سلسلة فارغة.لذلك يمكنك ببساطة حذف العمود من عبارة INSERT وسيتم تعيينه تلقائيًا على السلسلة الفارغة (بشرط أن يحتوي العمود على قيد NOT NULL).

نصائح أخرى

بفضل بعض الإجابات، أدركت أن المشكلة قد تكون في MDB2 API، وليس في أوامر PHP أو MYSQL نفسها.من المؤكد أنني وجدت هذا في الأسئلة الشائعة لـ MDB2:

  • لماذا تنتهي السلاسل الفارغة بالقيمة NULL في قاعدة البيانات؟لماذا أحصل على خالية غير مسموح بها في حقول النص الخالية من الحدث على الرغم من أن القيمة الافتراضية هي ""؟
    • المشكلة هي أنه بالنسبة لبعض RDBMS (معظم أوراكل) ، فإن سلسلة فارغة خالية.لذلك يوفر MDB2 خيار قابلية النقل لفرض نفس السلوك على جميع RDBMS.
    • نظرًا لأن جميع خيارات قابلية النقل يتم تمكينها افتراضيًا ، فسيتعين عليك تعطيل الميزة إذا كنت لا ترغب في الحصول على هذا السلوك:$ mdb2-> setOption ('portability' ، mdb2_portability_all ^ mdb2_portable_empty_to_null) ؛

شكرا لكل من قدم إجابات مدروسة.

أدرك أن هذا السؤال تمت الإجابة عليه وتقاعد إلى حد كبير، لكنني وجدته أثناء البحث عن إجابات لموقف مماثل ولا أستطيع مقاومة رمي قبعتي في الحلبة.

بدون معرفة ما يرتبط به العمود NULL/""، لا أستطيع معرفة مدى الأهمية الحقيقية لسلسلة فارغة.هل تعني السلسلة الفارغة شيئًا في حد ذاتها (مثل، إذا أقنعت القاضي بالسماح لي بتغيير اسمي إلى لا شيء ببساطة، سأكون منزعجًا حقًا إذا ظهر اسمي في رخصة قيادتي على أنه NULL.اسمي سيكون!

ومع ذلك، فإن السلسلة الفارغة (أو الفارغة، أو العدم الذي يمثل شيئًا ما، وليس مجرد عدم وجود أي شيء (مثل NULL)) يمكن أيضًا أن تعني ببساطة "NOT NULL" أو "لا شيء، ولكنها لا تزال ليست Null".يمكنك حتى أن تذهب في الاتجاه الآخر وتقترح أن غياب القيمة NULL يجعلها أقل شيئًا من Null، لأن Null على الأقل له اسم يمكنك قوله بصوت عالٍ!

وجهة نظري هي أنه إذا كانت السلسلة الفارغة تمثل تمثيلًا مباشرًا لبعض البيانات (مثل الاسم، أو ما أفضّل إدراجه بين الأرقام الموجودة في رقم هاتفي، وما إلى ذلك)، فإن خياراتك هي إما الجدال حتى تشعر بالألم للاستخدام المشروع لسلسلة فارغة أو لاستخدام شيء يمثل سلسلة فارغة ليست فارغة (مثل حرف تحكم ASCII أو ما يعادله من unicode، أو قيمة regex من نوع ما، أو الأسوأ من ذلك، رمز مميز تعسفي ولكنه غير مستخدم تمامًا ، يحب:◘

إذا كانت الخلية الفارغة تعني "ليست فارغة" حقًا، فيمكنك التفكير في طريقة أخرى للتعبير عنها.إحدى الطرق السخيفة والواضحة هي عبارة "ليست فارغة".لكن لدي حدس أن NULL تعني شيئًا مثل "ليس جزءًا من هذه المجموعة على الإطلاق" بينما تعني السلسلة الفارغة شيئًا مثل "هذا الرجل رائع، لم يحصل على وشم عصابته بعد".في هذه الحالة سأتوصل إلى مصطلح/اسم/فكرة لهذا الموقف، مثل "افتراضي" أو "مبتدئ" أو "معلق".

الآن، إذا كنت تريد بالفعل، عن طريق بعض الصدفة المجنونة، أن تمثل السلسلة الفارغة ما لا يستحق NULL، مرة أخرى، فابتكر رمزًا أكثر أهمية لذلك، مثل "-1" أو "SUPERNULL" أو "UGLIES".

في النظام الطبقي الهندي، أدنى طبقة هي الشدرا:المزارعين والعمال.تحت هذه الطبقة هم الداليت:"الغير ملموس".لا يتم اعتبارهم طبقة دنيا، لأن تصنيفهم على أنهم الطبقة الدنيا سيعتبر تلوثًا للنظام بأكمله.

لذا لا تدعوني بالجنون لأنني أعتقد أن السلاسل الفارغة قد تكون أسوأ من NULL!

'حتى المرة القادمة.

لقد وجدت الحل!

يقوم MDB2 بتحويل السلاسل الفارغة إلى NULL لأن خيار النقل MDB2_PORTABILITY_EMPTY_TO_NULL قيد التشغيل افتراضيًا (بفضل Oracle التي تعتبر السلاسل الفارغة فارغة).

قم بإيقاف تشغيل هذا الخيار عند الاتصال بقاعدة البيانات:

$options = array(
    'portability' => MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_EMPTY_TO_NULL
);
$res= & MDB2::connect("mysql://user:password@server/dbase", $options);

بينما 0 والسلاسل الفارغة هي متغيرات NULL هو غياب البيانات.وثق بي، من الأسهل كثيرًا أن تكتب استعلامًا

SELECT * from table where mything IS NULL بدلاً من محاولة الاستعلام عن سلاسل فارغة :/

ليست مجموعة فارغة من الاقتباسات، "" إفعل ذلك؟

أنا مرتبك.يبدو أنك تستخدم mysqli OO (من العلامات والنمط)، ولكن بناء الجملة يختلف عن يدوي على php.net، الذي ينص على القيام بذلك بدلاً من ذلك:

$query = "INSERT INTO mytable SET somevarchar = ?";
$value = "";
$prepared = $db->prepare($query);
$prepared->bind_param("s", $value);
$result = $prepared->execute();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top