ওরাকলে একাধিক সারিগুলিতে স্ট্রিং বিভক্ত করা হচ্ছে


104

আমি জানি পিএইচপি এবং এমওয়াইএসকিউএল দিয়ে কিছুটা উত্তর দেওয়া হয়েছে তবে আমি ভাবছিলাম যে কেউ যদি আমাকে ওরাকল 10 গ্রাম (অগ্রাধিকার দিয়ে) এবং 11 জি এর একাধিক সারিতে একটি স্ট্রিং (কীমাবদ্ধ সীমানা) বিভক্ত করার সহজতম পদ্ধতিটি শিখিয়ে দিতে পারেন তবে?

টেবিলটি নিম্নরূপ:

Name | Project | Error 
108    test      Err1, Err2, Err3
109    test2     Err1

আমি নিম্নলিখিত তৈরি করতে চাই:

Name | Project | Error
108    Test      Err1
108    Test      Err2 
108    Test      Err3 
109    Test2     Err1

আমি স্ট্যাকের চারপাশে কয়েকটি সম্ভাব্য সমাধান দেখেছি, তবে সেগুলি কেবল একটি একক কলামের জন্য গণ্য হয়েছে (কমা সীমানাঙ্কিত স্ট্রিং হিসাবে)। কোন সাহায্যের ব্যাপকভাবে প্রশংসা হবে।


উত্তর:


121

এটি একটি উন্নততর উপায় হতে পারে (এছাড়াও রেজিপ্সপ এবং এর মাধ্যমে সংযুক্ত):

with temp as
(
    select 108 Name, 'test' Project, 'Err1, Err2, Err3' Error  from dual
    union all
    select 109, 'test2', 'Err1' from dual
)
select distinct
  t.name, t.project,
  trim(regexp_substr(t.error, '[^,]+', 1, levels.column_value))  as error
from 
  temp t,
  table(cast(multiset(select level from dual connect by  level <= length (regexp_replace(t.error, '[^,]+'))  + 1) as sys.OdciNumberList)) levels
order by name

সম্পাদনা : এখানে প্রশ্নের একটি সহজ (যেমন "গভীরতায় নয়") রয়েছে।

  1. length (regexp_replace(t.error, '[^,]+')) + 1regexp_replaceডিলিমিটার নয় এমন কোনও কিছু মুছতে ব্যবহার করে (এই ক্ষেত্রে কমা) এবং length +1কতগুলি উপাদান (ত্রুটি) রয়েছে তা পেতে।
  2. select level from dual connect by level <= (...)ব্যবহারসমূহ একটি হায়ারারকিকাল কোয়েরি সাথে খেলাগুলি সংখ্যা ক্রমেই বেড়ে ত্রুটি মোট সংখ্যা 1 থেকে পাওয়া একটি কলাম তৈরি করুন।

    পূর্বরূপ:

    select level, length (regexp_replace('Err1, Err2, Err3', '[^,]+'))  + 1 as max 
    from dual connect by level <= length (regexp_replace('Err1, Err2, Err3', '[^,]+'))  + 1
  3. table(cast(multiset(.....) as sys.OdciNumberList)) ওরাকল ধরণের কিছু ingালাই করে।
    • দ্য cast(multiset(.....)) as sys.OdciNumberListরূপান্তরগুলির একাধিক সংগ্রহের (মূল ডেটা সেটে প্রতিটি সারির জন্য এক সংগ্রহ) সংখ্যার একটি একক সংগ্রহ, OdciNumberList মধ্যে।
    • table()ফাংশন একটি resultset মধ্যে একটি সংগ্রহ রূপান্তরিত করে।
  4. FROMএকটি যোগদান ছাড়া ক্রস জয়েন তৈরি করে আপনার ডেটাসেট এবং মাল্টিসিটের মধ্যে । ফলস্বরূপ, 4 টি ম্যাচ সহ ডেটা সেট ডেটার একটি সারি 4 বার পুনরাবৃত্তি করবে ("কলাম_মূল্য" নামক কলামে ক্রমবর্ধমান সংখ্যার সাথে)।

    পূর্বরূপ:

    select * from 
    temp t,
    table(cast(multiset(select level from dual connect by  level <= length (regexp_replace(t.error, '[^,]+'))  + 1) as sys.OdciNumberList)) levels
  5. trim(regexp_substr(t.error, '[^,]+', 1, levels.column_value))এর column_valueজন্য nth_appearance / ocurrence পরামিতি হিসাবে ব্যবহার করেregexp_substr
  6. আপনি t.name, t.projectসহজেই দৃশ্যধারণের জন্য আপনার ডেটা সেট থেকে ( উদাহরণ হিসাবে) কিছু অন্যান্য কলাম যুক্ত করতে পারেন other

ওরাকল ডক্সের কয়েকটি উল্লেখ:


7
সতর্ক থাকুন! তালিকায় '[^,]+'পার্স করার জন্য ফর্ম্যাটটির একটি রেজেক্স যদি তালিকায় কোনও নাল উপাদান থাকে তবে সঠিক আইটেমটি ফিরিয়ে দেয় না। : আরও তথ্যের জন্য এখানে দেখুন stackoverflow.com/questions/31464275/...
Gary_W

13
11 জি থেকে আপনি regexp_count(t.error, ',')পরিবর্তে ব্যবহার করতে পারেনlength (regexp_replace(t.error, '[^,]+')) যা আরও একটি পারফরম্যান্স উন্নতি করতে পারে
ftefan Oravec

1
"সাধারণ" সংযোগের সাথে 485 সেকেন্ড। এই ভাবে 0.296 সেকেন্ড। আপনি রক! এখন আমাকে যা করতে হবে তা বোঝা যাচ্ছে এটি কীভাবে কাজ করে। :-)
বব জার্ভিস -

@ BobJarvis এটি কী করে তা ব্যাখ্যা করার জন্য একটি সম্পাদনা যুক্ত করেছে। বানান / ব্যাকরণ সংশোধন স্বাগত।
নেফ্রেও

"স্বীকৃত উত্তরের কর্মক্ষমতা খারাপ রয়েছে" - এই বিষয়টিতে গৃহীত উত্তর কী? লিঙ্কটি অন্য পোস্টের রেফারেন্স ব্যবহার করুন।
0xdb

28

নিয়মিত এক্সপ্রেশন একটি দুর্দান্ত জিনিস :)

with temp as  (
       select 108 Name, 'test' Project, 'Err1, Err2, Err3' Error  from dual
       union all
       select 109, 'test2', 'Err1' from dual
     )

SELECT distinct Name, Project, trim(regexp_substr(str, '[^,]+', 1, level)) str
  FROM (SELECT Name, Project, Error str FROM temp) t
CONNECT BY instr(str, ',', 1, level - 1) > 0
order by Name

1
হাই আপনি কি দয়া করে আমাকে পরিষ্কার করতে পারেন কেন আমি
কোয়েরিতে

2
বিশেষত বিশাল টেবিলগুলিতে @ জগদীশজির কারণে এই ক্যোয়ারীটি ব্যবহারযোগ্য।
মাইকেল-ও

3
অত্যন্ত ধীর গতির, নীচে আরও ভাল উত্তর রয়েছে
মোরকফি

স্বচ্ছলতার কারণ হ'ল প্রতিটি সংযুক্তি Nameসংযুক্ত থাকে, যা আপনি সরিয়ে দিলে দেখা যায় distinct। দুর্ভাগ্যবশত যোগ and Name = prior Nameকরার connect byদফা কারণ ORA-01436: CONNECT BY loop in user data
মিক

আপনি (বা প্রাথমিক কীটি যাই হোক না কেন) ORA-01436যোগ করে ত্রুটি এড়াতে পারবেন এবংAND name = PRIOR name AND PRIOR SYS_GUID() IS NOT NULL
ডেভিড ফ্যাবার

28

নীচের দুটি মধ্যে একটি বিশাল পার্থক্য আছে:

  • একটি একক সীমানাযুক্ত স্ট্রিং বিভক্ত করা
  • টেবিলের একাধিক সারিগুলির জন্য সীমানাযুক্ত স্ট্রিংগুলি বিভক্ত করা।

আপনি যদি সারিগুলিকে সীমাবদ্ধ না করেন, তবে সংযোগ বিধি দ্বারা একাধিক সারি তৈরি হবে এবং পছন্দসই আউটপুট দেবে না।

নিয়মিত এক্সপ্রেশন ছাড়াও আরও কয়েকটি বিকল্প ব্যবহার করছে:

  • XMLTable
  • মডেল ক্লজ

সেটআপ

SQL> CREATE TABLE t (
  2    ID          NUMBER GENERATED ALWAYS AS IDENTITY,
  3    text        VARCHAR2(100)
  4  );

Table created.

SQL>
SQL> INSERT INTO t (text) VALUES ('word1, word2, word3');

1 row created.

SQL> INSERT INTO t (text) VALUES ('word4, word5, word6');

1 row created.

SQL> INSERT INTO t (text) VALUES ('word7, word8, word9');

1 row created.

SQL> COMMIT;

Commit complete.

SQL>
SQL> SELECT * FROM t;

        ID TEXT
---------- ----------------------------------------------
         1 word1, word2, word3
         2 word4, word5, word6
         3 word7, word8, word9

SQL>

এক্সএমএল টেবিল ব্যবহার :

SQL> SELECT id,
  2         trim(COLUMN_VALUE) text
  3  FROM t,
  4    xmltable(('"'
  5    || REPLACE(text, ',', '","')
  6    || '"'))
  7  /

        ID TEXT
---------- ------------------------
         1 word1
         1 word2
         1 word3
         2 word4
         2 word5
         2 word6
         3 word7
         3 word8
         3 word9

9 rows selected.

SQL>

মডেল ক্লজটি ব্যবহার করে :

SQL> WITH
  2  model_param AS
  3     (
  4            SELECT id,
  5                      text AS orig_str ,
  6                   ','
  7                          || text
  8                          || ','                                 AS mod_str ,
  9                   1                                             AS start_pos ,
 10                   Length(text)                                   AS end_pos ,
 11                   (Length(text) - Length(Replace(text, ','))) + 1 AS element_count ,
 12                   0                                             AS element_no ,
 13                   ROWNUM                                        AS rn
 14            FROM   t )
 15     SELECT   id,
 16              trim(Substr(mod_str, start_pos, end_pos-start_pos)) text
 17     FROM     (
 18                     SELECT *
 19                     FROM   model_param MODEL PARTITION BY (id, rn, orig_str, mod_str)
 20                     DIMENSION BY (element_no)
 21                     MEASURES (start_pos, end_pos, element_count)
 22                     RULES ITERATE (2000)
 23                     UNTIL (ITERATION_NUMBER+1 = element_count[0])
 24                     ( start_pos[ITERATION_NUMBER+1] = instr(cv(mod_str), ',', 1, cv(element_no)) + 1,
 25                     end_pos[iteration_number+1] = instr(cv(mod_str), ',', 1, cv(element_no) + 1) )
 26                 )
 27     WHERE    element_no != 0
 28     ORDER BY mod_str ,
 29           element_no
 30  /

        ID TEXT
---------- --------------------------------------------------
         1 word1
         1 word2
         1 word3
         2 word4
         2 word5
         2 word6
         3 word7
         3 word8
         3 word9

9 rows selected.

SQL>

1
আপনি কি আরও বিস্তারিত বলতে পারেন, কেন সেখানে থাকতে হবে ('"' || REPLACE(text, ',', '","') || '"')এবং বন্ধনীগুলি সরানো যাবে না? ওরাকল ডক্স ([ docs.oracle.com/datedia/121/SQLRF/function268.htm ) আমার কাছে পরিষ্কার নয়। এটা কি XQuery_string?
বেতলিস্তা

@ বিটলিস্ট এটি একটি এক্সকিউরি এক্সপ্রেশন।
ললিত কুমার বি

কোনও কারণে XMLTABLE সমাধান ক্রমাগত মিশ্র দৈর্ঘ্যের সারিগুলির জন্য শেষ এন্ট্রি আউটপুট করতে ব্যর্থ হয়। যেমন। সারি 1: 3 শব্দ; সারি 2: 2 শব্দ, সারি3: 1 শব্দ; সারি 4: 2 শব্দ, সারি 5: 1 শব্দ - শেষ শব্দটি আউটপুট দেবে না। সারিগুলির অর্ডার দেওয়া কোনও বিষয় নয়।
জ্ঞানডিফ 31:38

7

এর আরও কয়েকটি উদাহরণ:

SELECT trim(regexp_substr('Err1, Err2, Err3', '[^,]+', 1, LEVEL)) str_2_tab
  FROM dual
CONNECT BY LEVEL <= regexp_count('Err1, Err2, Err3', ',')+1
/

SELECT trim(regexp_substr('Err1, Err2, Err3', '[^,]+', 1, LEVEL)) str_2_tab
  FROM dual
CONNECT BY LEVEL <= length('Err1, Err2, Err3') - length(REPLACE('Err1, Err2, Err3', ',', ''))+1
/

এছাড়াও, DBMS_UTILITY.comma_to_table এবং টেবিল_ টো_কমমা ব্যবহার করতে পারে: http://www.oracle-base.com/articles/9i/useful-procedures-and-function-9i.php#DBMS_UTILITY.comma_to_table


সচেতন থাকুন যে comma_to_table()কেবল টোকেনগুলির সাথেই কাজ করে যা ওরাকল এর ডাটাবেস অবজেক্ট নামকরণের কনভেনশনগুলির সাথে খাপ খায়। এটি '123,456,789'উদাহরণস্বরূপ একটি স্ট্রিং উপর ছুড়ে দেওয়া হবে ।
এপিসি

7

আমি পাইপলাইনযুক্ত টেবিল ফাংশনটি ব্যবহার করে একটি ভিন্ন পদ্ধতির প্রস্তাব করতে চাই। এটি কিছুটা XMLTABLE এর কৌশলটির সাথে সমান, আপনি অক্ষরের স্ট্রিংকে বিভক্ত করার জন্য নিজস্ব কাস্টম ফাংশন সরবরাহ করছেন তা বাদ দিয়ে:

-- Create a collection type to hold the results
CREATE OR REPLACE TYPE typ_str2tbl_nst AS TABLE OF VARCHAR2(30);
/

-- Split the string according to the specified delimiter
CREATE OR REPLACE FUNCTION str2tbl (
  p_string    VARCHAR2,
  p_delimiter CHAR DEFAULT ',' 
)
RETURN typ_str2tbl_nst PIPELINED
AS
  l_tmp VARCHAR2(32000) := p_string || p_delimiter;
  l_pos NUMBER;
BEGIN
  LOOP
    l_pos := INSTR( l_tmp, p_delimiter );
    EXIT WHEN NVL( l_pos, 0 ) = 0;
    PIPE ROW ( RTRIM( LTRIM( SUBSTR( l_tmp, 1, l_pos-1) ) ) );
    l_tmp := SUBSTR( l_tmp, l_pos+1 );
  END LOOP;
END str2tbl;
/

-- The problem solution
SELECT name, 
       project, 
       TRIM(COLUMN_VALUE) error
  FROM t, TABLE(str2tbl(error));

ফলাফল:

      NAME PROJECT    ERROR
---------- ---------- --------------------
       108 test       Err1
       108 test       Err2
       108 test       Err3
       109 test2      Err1

এই ধরণের পদ্ধতির সমস্যাটি হ'ল প্রায়শই অপ্টিমাইজার টেবিলের ক্রিয়াকলাপের কার্ডিনালিটিটি জানতে পারে না এবং এটি অনুমান করতে হবে। এটি আপনার কার্যকরকরণ পরিকল্পনার পক্ষে ক্ষতিকারক ক্ষতিকারক হতে পারে, সুতরাং এই সমাধানটি অপ্টিমাইজারের জন্য কার্যকরকরণের পরিসংখ্যান সরবরাহ করতে বাড়ানো যেতে পারে।

আপনি উপরের ক্যোয়ারিতে একটি এক্সপ্ল্যান প্ল্যান চালিয়ে এই অপ্টিমাইজারের প্রাক্কলনটি দেখতে পারেন:

Execution Plan
----------------------------------------------------------
Plan hash value: 2402555806

----------------------------------------------------------------------------------------------
| Id  | Operation                          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                   |         | 16336 |   366K|    59   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                      |         | 16336 |   366K|    59   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL                | T       |     2 |    42 |     3   (0)| 00:00:01 |
|   3 |   COLLECTION ITERATOR PICKLER FETCH| STR2TBL |  8168 | 16336 |    28   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------

যদিও সংগ্রহের কেবল 3 টি মান রয়েছে, অপ্টিমাইজারটির পক্ষে 8168 সারি অনুমান করা হয়েছে (ডিফল্ট মান)। এটি প্রথমে অপ্রাসঙ্গিক বলে মনে হতে পারে, তবে উপ-অনুকূল পরিকল্পনার সিদ্ধান্ত নেওয়ার জন্য এটি অপ্টিমাইজারের পক্ষে যথেষ্ট।

সমাধানটি সংগ্রহের পরিসংখ্যান সরবরাহ করার জন্য অপ্টিমাইজার এক্সটেনশানগুলি ব্যবহার করা হয়:

-- Create the optimizer interface to the str2tbl function
CREATE OR REPLACE TYPE typ_str2tbl_stats AS OBJECT (
  dummy NUMBER,

  STATIC FUNCTION ODCIGetInterfaces ( p_interfaces OUT SYS.ODCIObjectList )
  RETURN NUMBER,

  STATIC FUNCTION ODCIStatsTableFunction ( p_function  IN  SYS.ODCIFuncInfo,
                                           p_stats     OUT SYS.ODCITabFuncStats,
                                           p_args      IN  SYS.ODCIArgDescList,
                                           p_string    IN  VARCHAR2,
                                           p_delimiter IN  CHAR DEFAULT ',' )
  RETURN NUMBER
);
/

-- Optimizer interface implementation
CREATE OR REPLACE TYPE BODY typ_str2tbl_stats
AS
  STATIC FUNCTION ODCIGetInterfaces ( p_interfaces OUT SYS.ODCIObjectList )
  RETURN NUMBER
  AS
  BEGIN
    p_interfaces := SYS.ODCIObjectList ( SYS.ODCIObject ('SYS', 'ODCISTATS2') );
    RETURN ODCIConst.SUCCESS;
  END ODCIGetInterfaces;

  -- This function is responsible for returning the cardinality estimate
  STATIC FUNCTION ODCIStatsTableFunction ( p_function  IN  SYS.ODCIFuncInfo,
                                           p_stats     OUT SYS.ODCITabFuncStats,
                                           p_args      IN  SYS.ODCIArgDescList,
                                           p_string    IN  VARCHAR2,
                                           p_delimiter IN  CHAR DEFAULT ',' )
  RETURN NUMBER
  AS
  BEGIN
    -- I'm using basically half the string lenght as an estimator for its cardinality
    p_stats := SYS.ODCITabFuncStats( CEIL( LENGTH( p_string ) / 2 ) );
    RETURN ODCIConst.SUCCESS;
  END ODCIStatsTableFunction;

END;
/

-- Associate our optimizer extension with the PIPELINED function   
ASSOCIATE STATISTICS WITH FUNCTIONS str2tbl USING typ_str2tbl_stats;

ফলাফল কার্যকরকরণ পরিকল্পনা পরীক্ষা করা:

Execution Plan
----------------------------------------------------------
Plan hash value: 2402555806

----------------------------------------------------------------------------------------------
| Id  | Operation                          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                   |         |     1 |    23 |    59   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                      |         |     1 |    23 |    59   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL                | T       |     2 |    42 |     3   (0)| 00:00:01 |
|   3 |   COLLECTION ITERATOR PICKLER FETCH| STR2TBL |     1 |     2 |    28   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------

আপনি দেখতে পাচ্ছেন যে উপরের পরিকল্পনায় কার্ডিনালিটিটি 8196 অনুমান করা মান নয়। এটি এখনও সঠিক নয় কারণ আমরা ফাংশনে স্ট্রিংয়ের পরিবর্তে একটি কলামটি পাস করছি।

এই বিশেষ ক্ষেত্রে একটি ঘনিষ্ঠ প্রাক্কলন দেওয়ার জন্য ফাংশন কোডটিতে কিছু টুইট করা প্রয়োজন, তবে আমি মনে করি সামগ্রিক ধারণাটি এখানে বেশ সুন্দরভাবে ব্যাখ্যা করা হয়েছে।

এই উত্তরে ব্যবহৃত str2tbl ফাংশনটি মূলত টম কিট দ্বারা বিকাশ করা হয়েছিল: https

অবজেক্টের ধরণের সাথে পরিসংখ্যানকে যুক্ত করার ধারণাটি এই নিবন্ধটি পড়ে আরও অনুসন্ধান করা যেতে পারে: http://www.oracle-developer.net/display.php?id=427

এখানে বর্ণিত কৌশলটি 10 ​​গ্রাম + এ কাজ করে।


4

REGEXP_COUNT ওরাকল 11 আই পর্যন্ত যোগ করা হয়নি। আর্টের সমাধান থেকে গৃহীত একটি ওরাকল 10 জি সমাধান।

SELECT trim(regexp_substr('Err1, Err2, Err3', '[^,]+', 1, LEVEL)) str_2_tab
  FROM dual
CONNECT BY LEVEL <=
  LENGTH('Err1, Err2, Err3')
    - LENGTH(REPLACE('Err1, Err2, Err3', ',', ''))
    + 1;

এর জন্য আমি কীভাবে একটি ফিল্টার যুক্ত করতে পারি তা বলতে পারি যে আমি কেবল নাম = '108' দিয়ে ফিল্টার করতে চাই। আমি ক্লজটি থেকে পরে যেখানে যুক্ত করার চেষ্টা করেছি তবে নকল দিয়ে শেষ করেছি।
ডিআরটৌলি

4

ওরাকল 12 সি থেকে শুরু করে আপনি ব্যবহার করতে পারেন JSON_TABLEএবং JSON_ARRAY:

CREATE TABLE tab(Name, Project, Error) AS
SELECT 108,'test' ,'Err1, Err2, Err3' FROM dual UNION 
SELECT 109,'test2','Err1'             FROM dual;

এবং ক্যোয়ারী:

SELECT *
FROM tab t
OUTER APPLY (SELECT TRIM(p) AS p
            FROM JSON_TABLE(REPLACE(JSON_ARRAY(t.Error), ',', '","'),
           '$[*]' COLUMNS (p VARCHAR2(4000) PATH '$'))) s;

আউটপুট:

┌──────┬─────────┬──────────────────┬──────┐
 Name  Project       Error         P   
├──────┼─────────┼──────────────────┼──────┤
  108  test     Err1, Err2, Err3  Err1 
  108  test     Err1, Err2, Err3  Err2 
  108  test     Err1, Err2, Err3  Err3 
  109  test2    Err1              Err1 
└──────┴─────────┴──────────────────┴──────┘

ডিবি <> ফিডাল ডেমো


1
আমি স্বীকার করি এটি একটি চতুর কৌশল but তবে সত্যই এটি আমার ধাঁধা দেবে যদি আমি কোনও কোড বেসে এসে পৌঁছে যাই।
এপিসি

@ এপিসি এটি এসকিউএল দিয়ে কী কী সম্ভব তা কেবল প্রদর্শন করে। যদি আমার কোডবেসে আমাকে এই জাতীয় কোড ব্যবহার করতে হয় তবে আমি অবশ্যই এটি কোনও ফাংশন দিয়ে মুড়িয়ে ফেলব বা একটি বর্ধিত মন্তব্য রেখে যাব :)
লুকাশ সাজ্জোদা

অবশ্যই. কেবল এটিই যে এই থ্রেডটি ওরাকলের সাথে স্ট্রিং টোকনাইজেশনের জন্য অন্যতম জনপ্রিয় হিট তাই আমি মনে করি নির্দোষদের নিজেদের থেকে রক্ষা করার জন্য আমাদের আরও বহিরাগত সমাধানগুলিতে ক্যাভেটগুলি অন্তর্ভুক্ত করা উচিত :)
এপিসি

3

XMLTABLE ব্যবহার করে এখানে একটি বিকল্প বাস্তবায়ন রয়েছে যা বিভিন্ন ডেটা ধরণের কাস্টিংয়ের অনুমতি দেয়:

select 
  xmltab.txt
from xmltable(
  'for $text in tokenize("a,b,c", ",") return $text'
  columns 
    txt varchar2(4000) path '.'
) xmltab
;

... বা যদি আপনার সীমিত স্ট্রিংগুলি একটি টেবিলের এক বা একাধিক সারিগুলিতে সঞ্চয় করা থাকে:

select 
  xmltab.txt
from (
  select 'a;b;c' inpt from dual union all
  select 'd;e;f' from dual
) base
inner join xmltable(
  'for $text in tokenize($input, ";") return $text'
  passing base.inpt as "input"
  columns 
    txt varchar2(4000) path '.'
) xmltab
  on 1=1
;

আমি মনে করি এই সমাধানটি ওরাকল 11.2.0.3 এবং পরবর্তী সংস্করণগুলির জন্য কাজ করে।
এপিসি

2

আমি অন্য একটি পদ্ধতি যুক্ত করতে চাই। এটির একটি পুনরাবৃত্ত অনুসন্ধানগুলি ব্যবহার করে, এমন কিছু যা আমি অন্য উত্তরে দেখিনি। এটি 11 জিআর 2 সাল থেকে ওরাকল দ্বারা সমর্থিত।

with cte0 as (
    select phone_number x
    from hr.employees
), cte1(xstr,xrest,xremoved) as (
        select x, x, null
        from cte0
    union all        
        select xstr,
            case when instr(xrest,'.') = 0 then null else substr(xrest,instr(xrest,'.')+1) end,
            case when instr(xrest,'.') = 0 then xrest else substr(xrest,1,instr(xrest,'.') - 1) end
        from cte1
        where xrest is not null
)
select xstr, xremoved from cte1  
where xremoved is not null
order by xstr

বিভক্ত চরিত্রের সাথে এটি বেশ নমনীয়। INSTRকলগুলিতে কেবল এটি পরিবর্তন করুন ।


2

দ্বারা সংযুক্ত বা regexp ব্যবহার না করে :

    with mytable as (
      select 108 name, 'test' project, 'Err1,Err2,Err3' error from dual
      union all
      select 109, 'test2', 'Err1' from dual
    )
    ,x as (
      select name
      ,project
      ,','||error||',' error
      from mytable
    )
    ,iter as (SELECT rownum AS pos
        FROM all_objects
    )
    select x.name,x.project
    ,SUBSTR(x.error
      ,INSTR(x.error, ',', 1, iter.pos) + 1
      ,INSTR(x.error, ',', 1, iter.pos + 1)-INSTR(x.error, ',', 1, iter.pos)-1
    ) error
    from x, iter
    where iter.pos < = (LENGTH(x.error) - LENGTH(REPLACE(x.error, ','))) - 1;

1

আমার একই সমস্যা ছিল, এবং এক্সএমলেটেবল আমাকে সহায়তা করেছিল:

নির্বাচন করুন আইডি, ছাঁটা (COLUMN_VALUE) পাঠ্য FROM t, xmltable (('' '' || পুনঃস্থাপন (পাঠ্য, ',', '","') || '' '))


0

ওরাকল ১১ জি এবং তারপরে, আপনি একটি পুনরাবৃত্ত সাব-কোয়েরি এবং সাধারণ স্ট্রিং ফাংশন ব্যবহার করতে পারেন (যা নিয়মিত এক্সপ্রেশন এবং সহসম্পর্কিত হায়ারারিকাল সাব-কোয়েরির চেয়ে দ্রুত হতে পারে):

ওরাকল সেটআপ :

CREATE TABLE table_name ( name, project, error ) as
 select 108, 'test',  'Err1, Err2, Err3' from dual union all
 select 109, 'test2', 'Err1'             from dual;

প্রশ্ন :

WITH table_name_error_bounds ( name, project, error, start_pos, end_pos ) AS (
  SELECT name,
         project,
         error,
         1,
         INSTR( error, ', ', 1 )
  FROM   table_name
UNION ALL
  SELECT name,
         project,
         error,
         end_pos + 2,
         INSTR( error, ', ', end_pos + 2 )
  FROM   table_name_error_bounds
  WHERE  end_pos > 0
)
SELECT name,
       project,
       CASE end_pos
       WHEN 0
       THEN SUBSTR( error, start_pos )
       ELSE SUBSTR( error, start_pos, end_pos - start_pos )
       END AS error
FROM   table_name_error_bounds

আউটপুট :

নাম | প্রকল্প | ত্রুটি
---: | : ------ | : ----
 108 | পরীক্ষা | Err1
 109 | পরীক্ষা 2 | Err1
 108 | পরীক্ষা | Err2
 108 | পরীক্ষা | Err3

ডিবি <> ফিডল এখানে


-1

আমি DBMS_UTILITY.comma_to _table ফাংশনটি ব্যবহার করলাম যা আসলে কোডটি নিম্নলিখিতভাবে কাজ করে

declare
l_tablen  BINARY_INTEGER;
l_tab     DBMS_UTILITY.uncl_array;
cursor cur is select * from qwer;
rec cur%rowtype;
begin
open cur;
loop
fetch cur into rec;
exit when cur%notfound;
DBMS_UTILITY.comma_to_table (
     list   => rec.val,
     tablen => l_tablen,
     tab    => l_tab);
FOR i IN 1 .. l_tablen LOOP
    DBMS_OUTPUT.put_line(i || ' : ' || l_tab(i));
END LOOP;
end loop;
close cur;
end; 

আমি আমার নিজস্ব টেবিল এবং কলামের নাম ব্যবহার করেছি


5
সচেতন থাকুন যে comma_to_table()কেবল টোকেনগুলির সাথেই কাজ করে যা ওরাকল এর ডাটাবেস অবজেক্ট নামকরণের কনভেনশনগুলির সাথে খাপ খায়। এটি '123,456,789'উদাহরণস্বরূপ একটি স্ট্রিং উপর ছুড়ে দেওয়া হবে ।
এপিসি

আমরা কি অস্থায়ী টেবিল ব্যবহার করে বাস্তবায়ন করতে পারি?
স্মার্ট 3003

1
উম্ম, অন্যান্য সমস্ত কার্যক্ষম সমাধানের পরেও কেন আমরা অস্থায়ী টেবিলগুলি ব্যবহার করতে চাই যা ডেটাগুলিকে বাস্তবায়নের বিশাল ওভারহেড সহ আসে?
এপিসি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.