Oracle OCI: استعلام مع حقل التاريخ
سؤال
تم تجميع العميل مع OCI: 10.2.0.4.0
الخادم: إصدار Oracle9i Enterprise Edition 9.2.0.4.0
الاستعلام الإشكالي هو:
SELECT CODIGO FROM LOG WHERE TEL = :telnumber AND DATE_PROC = '05-JUL-08'
وصف الجدول:
SQL>describe LOG;
TEL NOT NULL VARCHAR2(15)
CODIGO NOT NULL VARCHAR2(20)
DATE_PROC NOT NULL DATE
على الرغم من أن الأمر قد يبدو بسيطًا ، عند تنفيذه مباشرة على الخادم باستخدام SQLPlus ، فإنه يعيد نتيجة ، ولكن عند تنفيذه من التطبيق الذي يستخدم OCI ، يعود هذا الاستعلام OCI_NO_DATA
دائماً. في البداية ، كانت قيمة التاريخ أيضًا عنصرًا نائبًا ، لكنني اكتشفت أنه حتى إعطاء حرفي مثل '05-JUL-08'
لم ينجح. لقد جربت ما يلي:
- لقد جربت الأساسيات: الاستعلام عن DB من العميل يعمل. هذا هو الذي يعطيني المتاعب
ما يلي يعمل:
SELECT CODIGO FROM LOG WHERE TEL = :telnumber
التنفيذ
ALTER SESSION SET NLS_DATE_FORMAT="DD-MM-YYYY";
قبل الاستعلام في كل من الخادم والعميل. نفس النتيجة: يقوم الخادم بإرجاع البيانات ، العميلOCI_NO_DATA
- حاول التغيير
DATE_PROC
شكل ، يجمع هذا مع استخدامTO_DATE()
. نفس النتيجة. - بحثت ، بحثت ، بحث. لا اجابة
أنا يائسة بعض الشيء للعثور على إجابة ، وسأقدر أي مساعدة ويمكنني تقديم أكبر عدد ممكن من التفاصيل حسب الحاجة. شكرًا.
--- مزيد من المعلومات ---
update log set DATE_PROC = TO_DATE('20080705162918', 'YYYYMMDDHH24MISS') where CODIGO='BancoOne';
لقد جربت مجموعات مختلفة باستخدام Trunc () و "Set Set Set Set NLS_Date_Format" ... وهذا ما أحصل عليه:
SELECT CODIGO FROM LOG WHERE TEL = 11223344 AND DATE_PROC = TO_DATE('20080705162918', 'YYYYMMDDHH24MISS');
في الخادم: إرجاع: "Bancoone" (قيمة جيدة)
في تطبيق OCI: إرجاع OCI_NO_DATA
SELECT CODIGO FROM LOG WHERE TEL = 11223344 AND trunc(DATE_PROC) = TO_DATE('20080705', 'YYYYMMDD');
في الخادم: إرجاع: "Bancoone"
في تطبيق OCI: إرجاع "Bancoone"
لذا فإن النقطة هي ، لماذا يعطي تطبيق OCI نتائج مختلفة إذا كان كلاهما يصل إلى نفس خادم DB؟
أيضًا ، لتوضيح الغرض من تطبيق OCI: يحتوي على استعلام ليتم تكوينه من قبل المستخدم. الفكرة هي أن المستخدم سيؤدي إلى تكييف الاستعلام حسب الرغبة في ملاءمة حقل التاريخ الموجود في Desty DB ، ولهذا السبب يجب ألا أتضمن عبارات "ALTER SETATE SET NLS_DATE_FORMAT" في الكود الخاص بي ، حيث لن أعرف تنسيق التاريخ. وبهذه الطريقة ، أريد توفير المرونة للمستخدم ، ولا تعتمد على تنسيقات تاريخ محددة. هل لهذا معنى؟ أي اقتراحات؟
المحلول
عمودك Date_proc هو تاريخ ، يجب عليك دائماً قارنه بتاريخ و مطلقا الاعتماد على تحويل البيانات الضمني.
جرب هذا:
SELECT CODIGO FROM LOG WHERE TEL = :telnumber AND DATE_PROC = DATE '2008-07-05'
أو هذا:
SELECT CODIGO
FROM LOG
WHERE TEL = :telnumber
AND DATE_PROC = to_date('05-JUL-08', 'DD-MON-RR')
إذا استطعت ، الامتناع عن استخدام تنسيق التاريخ في الكود الخاص بك يستخدم الحروف لعدة أشهر (لأن الرمز سوف تفشل عندما تقوم بتغيير اللغة الافتراضية) واثنين فقط من chars لسنوات (غموض القرن). أحب الاستخدام 'YYYY/MM/RR'
لأنه سيتم فرز هذا التنسيق كتاريخ أصلي.
نصائح أخرى
كيف تم إدخال السجلات؟
تقوم حقول التاريخ بتخزين معلومات الوقت ، وبالتالي عند إدخال السجلات باستخدام SYSDATE ، سيحتوي حقل التاريخ على "قيم" مختلفة للسجلات خلال ذلك اليوم. عندما تقوم بتنفيذ Date_proc = '05 -jul-08 '، فأنت تقول أين تساوي Date_Proc بالضبط 5 يوليو 2008 في الساعة 12:01:00. إذا قمت بإدخال السجل في الساعة 12:01 مع Sysdate ، فلن يتم إرجاعه. هل حاولت استخدام A بين أو trunc؟
هنا مثال:
drop table test_date;
create table test_date (id number, ud date);
insert into test_date values (1, '15-jan-10');
insert into test_date values (2, '15-jan-10');
insert into test_date values (3, '15-jan-10');
insert into test_date values (6, sysdate); -- sysdate as of writing is 15-JAN-2010 08:01:55
insert into test_date values (7, sysdate); -- sysdate as of writing is 15-JAN-2010 08:01:55
insert into test_date values (8, '16-jan-10');
commit;
select id, ud, to_char(ud, 'dd-MON-yyyy HH:MM:SS') from test_date where ud = '15-jan-10';
---------------------- ------------------------- --------------------
1 15-JAN-10 15-JAN-2010 12:01:00
2 15-JAN-10 15-JAN-2010 12:01:00
3 15-JAN-10 15-JAN-2010 12:01:00
select id, ud, to_char(ud, 'dd-MON-yyyy HH:MM:SS') from test_date where trunc(ud) = '15-jan-2010';
---------------------- ------------------------- --------------------
1 15-JAN-10 15-JAN-2010 12:01:00
2 15-JAN-10 15-JAN-2010 12:01:00
3 15-JAN-10 15-JAN-2010 12:01:00
6 15-JAN-10 15-JAN-2010 08:01:55
7 15-JAN-10 15-JAN-2010 08:01:55
أود أن أقول أنك تطرح السؤال الخطأ.
يعتمد Oracle على مشاركة SQL للأداء ، وعندما تلتزم بسلسلة ، مثل "20080705" ، لا يمكن مشاركة SQL. تفاصيل هنا.
لذلك يجب أن تكون قيمة البيانات عنصرًا نائبًا ويجب أن تكون من نوع البيانات الصحيح (التاريخ). المثال هنا يجب أن يساعد في القيام بذلك.
ومع ذلك ، إذا كان هذا يعمل
SELECT CODIGO FROM LOG
WHERE TEL = 11223344 AND
trunc(DATE_PROC) = TO_DATE('20080705', 'YYYYMMDD');
لكن هذا لا
SELECT CODIGO FROM LOG
WHERE TEL = 11223344
AND DATE_PROC = TO_DATE('20080705162918', 'YYYYMMDDHH24MISS');
سأحاول
SELECT TO_CHAR(DATE_PROC,'DD-MM-YYYY HH24:MI:SS') FROM LOG
WHERE TEL = 11223344 AND
trunc(DATE_PROC) = TO_DATE('20080705', 'YYYYMMDD');
كان لدينا هذا الخطأ فقط (OCI_NO_DATA) بسبب شخص يغير ساعة اليوم على جهاز الكمبيوتر الخاص به. عندما يعيدون التاريخ/الوقت إلى الوقت المناسب ، بدأ التطبيق يعمل بشكل جيد.