2012-03-26 17 views
5

मैं एक तालिका में एक स्तंभ जोड़ने की कोशिश कर रहा था लेकिन DEFAULT खंड के साथ एक आश्चर्यजनक प्रभाव मिला। मौजूदा पंक्तियों के साथ एक तालिका में, मैं बहुत की तरह एक नया स्तंभ कहा:क्या वेरिएन्टिक्स वाले कॉलम के लिए ओरेकल में समर्थित डिफ़ॉल्ट मान हैं?

alter table t add c char(1 char) default 'N' not null; 

जब मैं बाद में मेज पर एक चेक बाधा कहा, यह विफल रहा है:

alter table t add constraint chk check(c in ('N', 'Y')); 

कौन सा

ERROR at line 1: 
ORA-02293: cannot validate (T.CHK) - check constraint violated. 
में हुई

अन्य जानकारी:

  1. क्योंकि मैं इकाइयों को स्पष्ट रूप से सेट कर रहा हूं (यानी, चार (1) के विपरीत चार (1)), मैं nls_length_semanatics के मान को प्रासंगिक होने की अपेक्षा नहीं करता हूं।
  2. कॉलम को चार (1 char) के रूप में जोड़ने के बाद, नए जोड़े गए "एन" वास्तव में "एन" हैं और मुझे यकीन नहीं है कि अतिरिक्त व्हाइटस्पेस क्या है।
  3. कॉलम को चार (1 बाइट) के रूप में जोड़ना अपेक्षित काम करता है;
  4. कॉलम को "डिफ़ॉल्ट" एन 'नल "के बिना जोड़ना, इसके बाद सभी मौजूदा पंक्तियों को' एन 'में अपडेट करके, कॉलम को' नल 'में बदलने के बाद भी उम्मीद के अनुसार काम करता है।
  5. NLS_CHARACTERSET AL32UTF8 है, लेकिन मुझे अपेक्षा नहीं है कि यह प्रासंगिक भी हो।
  6. डाटाबेस ओरेकल 11 जी है; 11.2.0.1.0।

धन्यवाद।

+0

अद्यतन करने के लिए एक UPDATE जारी कर सकता है , इसे क्यों नहीं (1 बाइट)? – tbone

+2

अपनी जांच बाधा को 'चेक (सीएन (TO_NCHAR (' एन '), TO_NCHAR (' वाई ') के रूप में पुनः लिखने का प्रयास करें))। मुझे यकीन नहीं है कि चेक बाधाओं में फ़ंक्शन आमंत्रण की अनुमति है, लेकिन कम से कम एक शॉट के लायक हो सकता है। –

उत्तर

2

आपने oracle11g को टैग किया है, लेकिन आपने एक संस्करण निर्दिष्ट नहीं किया है।

यह मेरे लिए लिनक्स x86-64 पर 11.2.0.2 पर काम करता है।

SQL*Plus: Release 11.2.0.2.0 Production on Mon Mar 26 13:13:52 2012 

Copyright (c) 1982, 2010, Oracle. All rights reserved. 

Connected to: 
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production 
With the Partitioning, Real Application Clusters, Automatic Storage Management and OLAP options 

SQL> create table tt(a number); 

Table created. 

SQL> insert into tt values (1); 

1 row created. 

SQL> commit; 

Commit complete. 

SQL> alter table tt add c char(1 char) default 'N' not null; 

Table altered. 

SQL> alter table tt add constraint chk check(c in('N','Y')); 

Table altered. 

SQL> select * from tt; 

    A C 
---------- - 
    1 N 

SQL> column dump(c) format a30 
SQL> select c, length(c),dump(c) from tt; 

C LENGTH(C) DUMP(C) 
- ---------- ------------------------------ 
N  1 Typ=96 Len=1: 78 

तो .... शायद आपके संस्करण में एक बग है?

उम्मीद है कि मदद करता है।

+0

दिलचस्प। मैंने विंडोज और लिनक्स, ओरेकल 11.2.0.1.0 दोनों पर कोशिश की। तो शायद यह एक मामूली संस्करण बग है। मैं एक अद्यतन के साथ प्रयास करेंगे। धन्यवाद। –

+3

@ मार्क जे बॉबक - आपका डेटाबेस कैरेक्टर सेट क्या है? मेरा दांव यह है कि यह केवल उन डेटाबेस में होता है जिनमें परिवर्तनीय चौड़ाई वर्ण सेट होते हैं (यानी 'AL32UTF8')। –

+0

@ जस्टिनकेव एफटीडब्ल्यू! मैं सहमत हूं, मुझे लगता है कि यह परिवर्तनीय चौड़ाई चरित्र सेट है। ओरेकल को एक चर चौड़ाई वर्ण सेट द्वारा अनुमत अधिकतम चौड़ाई आवंटित करनी होगी, और शेष वर्णों के लिए पैड को अधिकतम बाइट्स का उपयोग नहीं करना होगा। –

2

ओआरए -022 9 3 त्रुटि का कारण, जैसा कि आपने पहले ही उल्लेख किया है, क्योंकि यह 'एन' के बजाय 'एन' (एक गद्दीदार सफेद जगह के साथ) डालने वाला है। तो आपकी बाधा का उल्लंघन किया जाता है।

अधिक दिलचस्प सवाल यह है कि, वह जगह क्यों जोड़ रही है? खैर, परिभाषा के अनुसार, एक CHAR निश्चित चौड़ाई है, जहां एक VARCHAR नहीं है। स्तंभ के लिए आवंटित संपूर्ण मेमोरी स्पेस को भरने के लिए एक CHAR हमेशा सफेद स्थान पैड करेगा। चूंकि आपने 1 चार्ज की चौड़ाई चुना है, और AL32UTF8 एक अलग चौड़ाई वर्ण सेट है, जो कि CHAR की निश्चित चौड़ाई प्रकृति के साथ संघर्ष प्रतीत होता है। ऐसा लगता है कि यह 'एन' द्वारा उपयोग नहीं किए जाने वाले अतिरिक्त बाइट को भरने के लिए गद्देदार हो जाता है। या, कम से कम, मुझे लगता है कि यह हो रहा है।

5

मुझे विश्वास है कि आप जो देख रहे एक बग है कि एक जोड़े को अलग अलग बातचीत

  • पहली बात पर निर्भर करता है, डेटाबेस वर्ण सेट एक चर चौड़ाई वर्ण सेट (यानी AL32UTF8) तो एक है कि हो गया है एकल चरित्र को चार बाइट स्टोरेज की आवश्यकता हो सकती है।
  • दूसरा, कॉलम वर्ण लंबाई अर्थशास्त्र
  • तीसरा, 11 से शुरू होने के साथ घोषित किया जाना चाहिए।1, ओरेकल ने एक ऑप्टिमाइज़ेशन जोड़ा ताकि यदि आप NOT NULL घोषित तालिका में एक कॉलम जोड़ते हैं और इसमें DEFAULT है कि ओरेकल तालिका के प्रत्येक पंक्ति में वास्तव में डिफ़ॉल्ट मान को संग्रहीत करने के बजाय डेटा डिक्शनरी अपडेट करके ऐसा कर सकता है।

जब दोनों चीजें सच होती हैं, ऐसा लगता है कि लौटाया गया मान 4 की लंबाई है और CHR(0) चरित्र के साथ गद्देदार है।

SQL> select * from v$version; 

BANNER 
-------------------------------------------------------------------------------- 
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production 
PL/SQL Release 11.2.0.1.0 - Production 
CORE 11.2.0.1.0  Production 
TNS for 64-bit Windows: Version 11.2.0.1.0 - Production 
NLSRTL Version 11.2.0.1.0 - Production 

SQL> create table foo(col1 number); 

Table created. 

SQL> insert into foo values(1); 

1 row created. 

SQL> commit; 

Commit complete. 

SQL> alter table foo add c char(1 char) default 'N' not null; 

Table altered. 

SQL> alter table foo add constraint chk_foo check(c in ('Y', 'N')); 
alter table foo add constraint chk_foo check(c in ('Y', 'N')) 
           * 
ERROR at line 1: 
ORA-02293: cannot validate (SCOTT.CHK_FOO) - check constraint violated 

SQL> select c, dump(c) from foo; 

C DUMP(C) 
---- ------------------------------ 
N Typ=1 Len=4: 78,0,0,0 

आप वास्तव में मूल्य के लिए मजबूर हैं तालिका में संग्रहीत करने के लिए, आप अपेक्षित व्यवहार जहां कोई CHR(0) गद्दी मिल जाएगा। तो अगर मैं तालिका में एक नई पंक्ति डालता हूं, तो यह गुजरता है।

SQL> insert into foo(col1) values (2); 

1 row created. 

SQL> select c, dump(c) from foo; 

C DUMP(C) 
---- ------------------------------ 
N Typ=1 Len=4: 78,0,0,0 
N Typ=1 Len=1: 78 

तुम भी अगर केवल मूल्यों होने के लिए 'एन' या 'वाई' कर रहे हैं कि वास्तव में पंक्तियाँ तालिका की पंक्तियां में मूल्य भंडारण नहीं कर रहे हैं

SQL> update foo 
    2  set c = 'N' 
    3 where c != 'N'; 

1 row updated. 

SQL> select c, dump(c) from foo; 

C DUMP(C) 
---- ------------------------------ 
N Typ=1 Len=1: 78 
N Typ=1 Len=1: 78 
+3

मेरा उदाहरण और उपरोक्त टिप्पणी भी देखें। यह स्पष्ट रूप से 11.2.0.1.0 में एक बग है, और 11.2.0.2.0 में तय किया गया है। –