इसका कोई मतलब नहीं है, और यह कुछ भी 'के लिए' नहीं है; आपका डेटा दूषित है, मुझे डर है। --
आपकी तालिका से वास्तविक मान है, लेकिन यह कोई संख्या नहीं है। संख्याओं के लिए Oracle का आंतरिक प्रतिनिधित्व नोट 1031902.6 में शामिल है यदि आपके पास उस तक पहुंच है, या यह यदि आप नहीं करते हैं तो इसे समझाते हैं
. यदि यह वास्तव में एक ऋणात्मक संख्या थी तो अंतिम हेक्साडेसिमल बाइट 66 होनी चाहिए। जो संख्या प्रतीत होती है उसे डंप करना - एक ऋण चिह्न के साथ, दो नहीं, जो अर्थहीन है - देता है:
select dump(-1331013400000000000000000000, 1016) from dual;
DUMP(-1331013400000000000000000000,1016)
----------------------------------------
Typ=2 Len=6: 31,58,46,64,43,66
Oracle में अमान्य संख्याएँ बनाना सीधा नहीं है (मुझे लगता है कि आप इसकी उम्मीद नहीं करेंगे), लेकिन यह एक ऐसी विधि है जिसका मैंने पहले उपयोग किया है। दोहरे ऋण चिह्न के अलावा और यह कि वे सभी समान लंबाई के हैं, एक संकेत यह है कि डंप किए गए मान को वापस एक संख्या में परिवर्तित करने से समान परिणाम नहीं मिलता है:
create table t42(value number);
declare
n number;
begin
dbms_stats.convert_raw_value('32ea004366', n);
insert into t42 (value) values (n);
end;
/
select value from t42;
VALUE
--------------------------------------
-<3:13400000000000000000000
यह Oracle 9i से है, जो अब मेरे पास 8i डेटाबेस के करीब है, इसलिए परिणाम थोड़े भिन्न हो सकते हैं।
to_number(value)
करने में सक्षम नहीं होना निश्चित रूप से बड़ा सुराग भी है; एक अंतर्निहित to_char()
है जब आप ऐसा करते हैं तो यह टेक्स्ट प्रस्तुति को एक संख्या में बदलने की कोशिश कर रहा है, जो त्रुटि बताता है। to_char()
मूल्य मेल नहीं खाता जो एक साधारण चयन या तो दिलचस्प है। यदि आप अपने डेटा के साथ ऐसा करते हैं तो आपको वही त्रुटि दिखाई देगी।
select to_number(value) from t42;
select to_number(value) from t42
*
ERROR at line 1:
ORA-01722: invalid number
select to_char(value) from t42;
TO_CHAR(VALUE)
----------------------------------------
-`003400000000000000000000
जब तक आप नहीं जानते कि खराब डेटा कहां से आया है और मूल डेटा अभी भी है, तो आप शायद इन मूल्यों को बचा नहीं सकते। मुझे लगता है कि सबसे अच्छा आप इसे अनदेखा कर सकते हैं, या इसे किसी ऐसी चीज़ से बदल सकते हैं जो माइग्रेट हो जाएगी - यदि फ़ील्ड शून्य है तो null
सुरक्षित विकल्प होगा, अन्यथा मुझे लगता है कि आपको एक जादुई मूल्य चुनना होगा।
प्रभावित पंक्तियों की पहचान और संशोधन एक फ़ंक्शन के माध्यम से किया जा सकता है; संभवतः कुछ ऐसा:
create or replace function null_bad_number(value number)
return number deterministic as
tmp_value number;
invalid_number exception;
pragma exception_init(invalid_number, -1722);
begin
select to_number(value) into tmp_value from dual;
return value;
exception
when invalid_number then
return null;
end;
/
पहले बनाए गए समान अमान्य मान और एक मान्य मान के साथ:
insert into t42 (value) values (0.9574875526618150);
select * from t42;
VALUE
----------
-`.003E+24
.957487553
update t42 set value = null
where value is not null
and null_bad_number(value) is null;
1 row updated.
select * from t42;
VALUE
----------
.957487553
किसी भी तरह से आदर्श नहीं है, लेकिन इस समय मुझे लगता है कि आप केवल वही बचा रहे हैं जो आप कर सकते हैं। आप पंक्तियों को अपडेट करने के बजाय हटा सकते हैं, या मान को किसी और चीज़ पर सेट कर सकते हैं, यह निर्भर करता है कि आप कैसे आगे बढ़ना चाहते हैं।
आप ओरेकल को यह देखने के लिए शामिल करने का प्रयास कर सकते हैं कि क्या वे यह पता लगा सकते हैं कि क्या हुआ और देखें कि क्या उनके पास मूल मूल्यों पर वापस जाने के लिए कोई चाल है - जो असंभव लगता है - लेकिन मुझे यकीन नहीं है कि आपको बहुत समर्थन मिलेगा इसके लिए डेटाबेस का इतना पुराना संस्करण।
बेशक, यह जाने बिना कि भ्रष्टाचार कैसे और कब पेश किया गया था (शायद एक डोडी आयात के माध्यम से, या एक छोटी गाड़ी ओसीआई कार्यक्रम के माध्यम से), आपको उस कॉलम और अन्य जगहों पर अन्य सभी डेटा की वैधता पर सवाल उठाना होगा। इस मामले में भ्रष्टाचार बहुत समान दिखता है - सभी अमान्य मान एक ही तरह से बनाए गए प्रतीत होते हैं - इसलिए आप ठीक हो सकते हैं। आम तौर पर हालांकि, कुछ ऐसा जो गलत बाइट्स को आंतरिक मान में डालता है, गलत, लेकिन फिर भी मान्य, मान को रोक सकता है। यह सही दिख सकता है, या यह मूल अपेक्षित मूल्य से परिमाण के आदेश हो सकता है, और वास्तव में बताने का कोई तरीका नहीं है।