لا يتطابق الحرفي إلى سلسلة التنسيق لـ Oracle SQL to_date على عمود سلسلة

StackOverflow https://stackoverflow.com/questions/3105003

  •  29-09-2019
  •  | 
  •  

سؤال

عزيزي SQL Gurus من Stack Overflow:

بيئة: وحي

أحاول أن أفهم لماذا لا يمكنني القيام باختيار to_date على عمود جدول يحتوي على سلاسل. لاحظ أن Tablez مع عمود من قيمة الاسم في المثال أدناه يحتوي على مجموعة من الأوتار ، بعضها هو التنسيق الصحيح ، على سبيل المثال 6/20/2010 00:00:00.

Tablez

| Value              |
| __________________ |
| 6/21/2010 00:00:00 |
| Somestring         |
| Some Other strings |
| 6/21/2010 00:00:00 |
| 6/22/2010 00:00:00 |

الأعمال التالية

SELECT To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') somedate 
          FROM tableX a, tableY b, tableZ c 
         WHERE Lower(a.name) = 'somedate' 
           AND a.id = b.other_id 
           AND b.id = c.new_id

هذا يعيد شيئًا مثل (وهو أمر جيد):

| somedate            |
| __________________  |
| 21.06.2010 00:00:00 |
| 21.06.2010 00:00:00 |
| 22.06.2010 00:00:00 |

ما يلي لا يعمل

SELECT To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') somedate 
          FROM properties$aud a, template_properties$aud b, consumable_properties$aud c 
         WHERE Lower(a.name) = 'somedate' 
           AND a.id = b.property_id 
           AND b.id = c.template_property_id 
           AND To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') IS NOT NULL

يعود مع:

ORA-01861: لا يتطابق الحرفي

ماذا أفتقد هنا؟ مجرد ملاحظة سريعة:

 ...
AND b.id = c.template_property_id 
AND To_Date(c.Value, 'DD.MM.YYYY HH24:MI:SS') IS NOT NULL

لا يعمل أيضًا.

شكرًا!!

هدف لتكون قادرًا على القيام بتاريخ بين الاستفسارات على C.Value من أجل تحديد نطاقات التاريخ.

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

المحلول

ترتيب أن أوراكل يقيم الشروط الموجودة في الفقرة التي لا يتم إصلاحها. وهذا يعني أنه يمكن أن تختار تقييم الحالة التي تحتوي على to_date قبل المعايير الأخرى ، وفي هذه الحالة سيفشل الاستعلام. لمنع ذلك ، أضف تلميح ordered_predicates إلى استعلامك ، ولكن كن على علم بأن هذا قد يتطلب ضبطًا يدويًا إضافيًا لتحسين الأداء.

SELECT /*+ ordered_predicates */
               To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') somedate 
          FROM properties$aud a, 
               template_properties$aud b, 
               consumable_properties$aud c 
         WHERE Lower(a.name) = 'somedate' 
           AND a.id = b.property_id 
           AND b.id = c.template_property_id 
           AND To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') IS NOT NULL

فيما يبدو ordered_predicates تم إهماله بدءًا من 10g. في هذه الحالة ، أعتقد أن خيارك الوحيد هو استخدام مسابقة فرعية بطريقة تضطر إلى التقييم لتقييمه أولاً (أي أنه لا يمكن الجمع بين الاستعلامات). أسهل طريقة للقيام بذلك هي وضعها rownum في بيان الاستعلام الداخلي.

SELECT To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') somedate 
  FROM (SELECT value 
          FROM properties$aud a, 
               template_properties$aud b, 
               consumable_properties$aud c 
         WHERE Lower(a.name) = 'somedate' 
           AND a.id = b.property_id 
           AND b.id = c.template_property_id
           AND rownum > 0) 
 WHERE To_Date(c.Value, 'MM/DD/YYYY HH24:MI:SS') IS NOT NULL

نصائح أخرى

create or replace function to_date_or_null(v_str_date in varchar2
        , v_str_fmt in varchar2 default null) return date as
begin
    if v_str_fmt is null then
        return to_date(v_str_date);
    else
        return to_date(v_str_date, v_str_fmt);
    end if;
exception
    when others then
        return null;
end to_date_or_null;
/

اختبارات:

SQL> select to_date_or_null('2000-01-01', 'YYYY-MM-DD') from dual -- Valid;

TO_DATE_OR_NULL('20
-------------------
2000-01-01 00:00:00

SQL> select to_date_or_null('Not a date at all') from dual -- Not Valid;

TO_DATE_OR_NULL('NO
-------------------


SQL> select to_date_or_null('2000-01-01') from dual -- Valid matches my NLS settings;

TO_DATE_OR_NULL('20
-------------------
2000-01-01 00:00:00

SQL> select to_date_or_null('01-Jan-00') from dual -- Does not match my NLS settings;

TO_DATE_OR_NULL('01
-------------------

هناك تقنية أخرى تضم التحويل في حالة ما. فمثلا

SELECT * FROM table
WHERE col_a = '1'
AND case when col_a = '1' then to_date(col_b,'DD/MM/YYYY') end = trunc(sysdate)

هذا يصبح سريعًا حقًا عندما تكون الجمل معقدة.

هل تريد التحقق مما إذا كان C.Value تنسيقًا صالحًا مع

AND To_Date(c.Value, 'DD.MM.YYYY HH24:MI:SS') IS NOT NULL

؟ لن ينجح هذا ، ستحتاج إلى إجراء الشيك بطريقة أخرى. يمكنك استخدام تعبير منتظم (أعتقد ، لا تستخدمه منذ فترة). الأفضل من ذلك إذا كان نموذج البيانات الخاص بك سيسمح لك بتمييز الصفوف المعنية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top