يحدث أن المنتج الذي نقوم بتطويره يعمل مع قواعد بيانات علائقية متعددة. الآن هذه هي MS SQL و Postgres و Oracle. كانت هناك عمليات إطلاق تحت الكثير من الأشياء من MySQL إلى المتوفى ، على الأرجح Firebird و Sybase الغريبة مع DB2 ، لكن هذه ليست القصة.
إذا كان كل شيء باستخدام MS SQL و Postgres أكثر قابلية للفهم ومألوفًا ، فعندئذٍ مع Oracle في كل مرة نواجه فيها بعض المفاجآت. سيلاحظ القارئ الذكي على الفور أن "أيدينا ملتوية" و "ببساطة لا نعرف كيف نطبخها" ، ولكن إذا أراد القارئ العزيز أن يعرف كيف varchar2
يختلف varchar (أو بالأحرى ) في أوراكل الشبيهة بالله عن إخوانه ، من فضلك ، تحت القط.
مثل جميع الأنظمة الحديثة ، نقوم بتخزين البيانات بتنسيق Unicode (حاليًا UTF-8). لماذا قد يكون هذا مهمًا لقواعد البيانات العلائقية؟
حسنًا ، على سبيل المثال ، إذا كان لديك مزيج من أنواع بيانات unicode وغير unicode في قاعدة البيانات الخاصة بك ، فلن تتمكن بعض برامج التشغيل من القيام بذلك. على سبيل المثال ، يمكن لبرنامج تشغيل JTDS - JDBC لخادم MS SQL أن يعمل إما في وضع Unicode أو في Ansi. وفقًا لذلك ، إذا قررت "حفظ" وإنشاء عمود بدون يونيكود (varchar / char) ، فستحصل على تحويل unicode-> ansi على مستوى إدراج البيانات في الجدول ، وعلى الأرجح ، تحقق التأثير المعاكس (على الأقل تباطؤ في إدخال البيانات ، وإلا وعلى البحث).
إذن القصة. يتحقق خادم التطبيق الخاص بنا من الحد الأقصى المسموح به للطول للحقول قبل إدخالها (من الضروري هنا اشتراط أن يتم إجراء الفحص ليس وفقًا لبيانات قاعدة البيانات ، ولكن وفقًا للبيانات الوصفية الداخلية) ، ولكن على الرغم من ذلك ، فإننا أحيانًا في إطار Oracle "نكتشف" خطأ مثلORA-12899: value too large for column.
أي نوع من الهجوم؟ علاوة على ذلك ، يتم إنشاء البرامج النصية بنفس الطريقة تقريبًا لجميع قواعد البيانات ، ولكن المشكلة تحدث في بعض الأحيان فقط وفي ظل Oracle فقط.
لن أعذب. اتضح أننا نقرأ مواصفات النوع varchar2
الذي يتم تخزين البيانات فيه باهتمام :)
لنقم بتغيير حجم العمود ، على سبيل المثال ، إلى ما يلي
alter table address modify street varchar2(150);
ما رأيك 150 هو الطول في الأحرف (كما في القواعد الأخرى بشكل عام)؟ تلميح - لا :) على الأرجح بالبايت.
وفي الرموز هو كذلك
alter table address modify street varchar2(150 char);
أولئك. بدون تحديد مواصفات char
- byte
نجد أنفسنا في المنطقة الرمادية من إعدادات قاعدة البيانات الافتراضية. علاوة على ذلك ، في جميع قواعد البيانات التي يمكننا الوصول إليها (بما في ذلك الإنتاج وليس لدينا فقط) ، يكون الإعداد الافتراضي هو البايت.
, UTF-8, , 4 ( 1 ANSI, 2 4 ).
Unicode !? , , , " ". .. , : legacy, , Unicode' " ", , backup 86 imp - .
? tool, , create table
char
:)
:
, , , .
SELECT value FROM NLSDATABASEPARAMETERS WHERE parameter='NLSLENGTHSEMANTICS';
, , " ":
SELECT TABLE_NAME, COLUMN_NAME, DATA_LENGTH, CHAR_USED
FROM USER_TAB_COLUMNS
WHERE DATA_TYPE = 'VARCHAR2' AND CHAR_USED = 'B'
ORDER BY TABLE_NAME, COLUMN_NAME
P.S. , , (, 100% ansi ), Unciode … ...
P.P.S. Regexp " " varchar2\(\s*\d+\s*\)
P.P.P.S. StackOverflow
PPPPS فيما يلي ما تفكر فيه Oracle حول تغيير قيمة المعلمة NLSLENGTHSEMANTICS
إلى شيء أكثر منطقية "توصي Oracle بشدة بعدم تعيين معلمة NLS LENGTH SEMANTICS على CHAR في المثيل أو ملف معلمة الخادم. قد يتسبب هذا في العديد من البرامج النصية للتثبيت الحالية إنشاء أعمدة بشكل غير متوقع مع دلالات طول الأحرف ، مما يؤدي إلى حدوث أخطاء في وقت التشغيل ، بما في ذلك تجاوزات المخزن المؤقت. " https://docs.oracle.com/cd/E24693 01 / server.11203 / e24448 / initparams149.htm