मैं ओरेकल बैकएंड (ओसीआई 8 फ़ंक्शंस) के साथ एक PHP संचालित अनुप्रयोग बनाए रखता हूं। ऐप को ओरेकल 10 जी एक्सई के साथ विकसित किया गया है और ग्राहक के किसी भी संस्करण पर तैनात किया गया है।CHAR semantics और ORA-01461
एप्लिकेशन एकल-बाइट टेक्स्ट (आईएसओ -885 9-15) को संभालता है और ओरेकल एक्सई के पश्चिमी यूरोपीय संस्करण के विरुद्ध विकास करते समय मुझे कोई समस्या नहीं हुई है। हालांकि, मैंने हाल ही में यूनिवर्सल संस्करण स्थापित किया है और गैर-ASCII वर्णों के साथ बड़े तार डालने पर मुझे समस्याएं आ रही हैं। यह संस्करण NLS_CHARACTERSET = AL32UTF8
सेट करता है; चूंकि मेरा ऐप WE8ISO8859P15
का उपयोग करता है ओरेकल चुपचाप मेरे इनपुट डेटा को आईएसओ -885 9-15 से यूटीएफ -8 (जो ठीक है) में परिवर्तित करता है। लेकिन ऐसा लगता है कि कुछ आकार की जांच गलत हो जाती है: 1500 €
वर्णों (आईएसओ -8889-15 में 1500 बाइट, यूटीएफ -8 में 4500 बाइट्स) के साथ एक स्ट्रिंग VARCHAR2(4000 CHAR)
कॉलम ओवरफ़्लो दिखाई देती है।
मैं इस परीक्षण तालिका बना लिया है:
CREATE TABLE FOO (
FOO_ID NUMBER NOT NULL ENABLE,
DATA_BYTE VARCHAR2(4000 BYTE),
DATA_CHAR VARCHAR2(4000 CHAR),
CONSTRAINT FOO_PK PRIMARY KEY (FOO_ID)
);
समस्या इस कोड के साथ reproduced किया जा सकता है:
<?php
$connection = oci_connect(DB_USER, DB_PASS, DB_CONN_STRING, 'WE8ISO8859P15');
if(!$connection){
$e = oci_error();
die(htmlspecialchars($e['message']));
}
$id = 1;
$data = str_repeat('€', 1500);
$sql = 'INSERT INTO FOO (FOO_ID, DATA_CHAR) ' .
'VALUES (:id, :data)';
$res = oci_parse($connection, $sql);
if(!$res){
$e = oci_error();
die(htmlspecialchars($e['message']));
}
if(!oci_bind_by_name($res, ':id', $id)){
$e = oci_error();
die(htmlspecialchars($e['message']));
}
if(!oci_bind_by_name($res, ':data', $data)){
$e = oci_error();
die(htmlspecialchars($e['message']));
}
if(!oci_execute($res, OCI_COMMIT_ON_SUCCESS)){
$e = oci_error();
die(htmlspecialchars($e['message']));
}
... जो चलाता है:
चेतावनी: oci_execute(): ORA-01461: sólo puede enlazar un valor लंबे पैरा डालने के लिए una columna लंबे
यह वही त्रुटि है जब मैं 4001 चार स्ट्रिंग डालने का प्रयास करता हूं। अगर मैं €€€
के बजाय xxx...
सम्मिलित यह नहीं होता है और अगर मैं के रूप में UTF-8 मेरी स्क्रिप्ट को बचाने ऐसा नहीं होता और इस तरह के रूप कनेक्ट:
<?php
$connection = oci_connect(DB_USER, DB_PASS, DB_CONN_STRING, 'AL32UTF8');
[अद्यतन: मेरा परीक्षण त्रुटिपूर्ण था । यूटीएफ -8 का उपयोग ओआरए -01461 से बच नहीं है]
मैं इस समस्या को कैसे ओवरराइड कर सकता हूं? NLS_CHARACTERSET डेटाबेस पैरामीटर कुछ ऐसा नहीं है जिसे मैं पर नियंत्रित करता हूं और अपना ऐप यूटीएफ -8 पर स्विच करने की संभावना अन्य समस्याओं का कारण बनता है (लगभग सभी हमारे ग्राहकों के पास एकल बाइट डेटाबेस हैं)।
आप सही हैं, मुझे मेरी यूटीएफ -8 टेस्ट स्क्रिप्ट में कोई त्रुटि हुई: यह ओआरए -01461 को भी ट्रिगर करता है। ऐसा लगता है कि 'वर्चर 2 (4000 चार्ज)' 4000 * बाइट्स * से अधिक नहीं रख सकता है। मैं अध्ययन करूंगा कि कॉलम आकार को कम करना है या 'सीएलओबी' पर स्विच करना है या नहीं। –
मुझे कुछ संदर्भ मिला: "जब आप VARCHAR2 कॉलम के साथ एक टेबल बनाते हैं, तो आप VARCHAR2 कॉलम के लिए अधिकतम स्ट्रिंग लम्बाई (बाइट्स या वर्णों में) 1 और 4000 ** बाइट्स ** के बीच निर्दिष्ट करते हैं।" - http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/datatype.htm#sthref3780 –
आप वैकल्पिक फिक्स्ड बाइट वर्णमाला का उपयोग करके समस्या को कम करने में सक्षम हो सकते हैं। उदाहरण के लिए जेए 16 एसजेआईएस जापानी अक्षरों के लिए दो बाइट्स का उपयोग करता है, और TH8TISASCII एक सिंगल बाइट थाई वर्णमाला –