2013-07-16 38 views
6

Tôi có trường địa chỉ có thể chứa 120 ký tự và cần chia nó thành ba cột khác nhau dài 40 ký tự.Cách chia cột VARCHAR trong Oracle trong ba cột

Ví dụ:

Table name: Address 
Column name: Street_Address 
Select Street_Address * from Address 

Output: 123 Main St North Pole Factory 44, near the rear entrance cross the street and turn left and keep walking straight.

tôi cần phải chia địa chỉ này vào address_1 address_2address_3.

Cả ba địa chỉ đều là varchar(40) kiểu dữ liệu.

Vì vậy, kết quả nên được một cái gì đó như thế này:

Address_1 
152 Main st North Pole Factory 44, near 

Address_2 
the rear entrance cross the street and 

Address_3 
turn left and keep walking straight. 

Xin lưu ý rằng từng lĩnh vực địa chỉ có thể mất đến 40 ký tự và phải là toàn bộ văn bản, nó không thể được rút ngắn trong nửa và trái nghĩa .

Tôi đang sử dụng cơ sở dữ liệu Oracle 11i.

+0

Bạn sẽ hiển thị các cột này ở đâu? Tại sao bạn không chia nó ở cấp ứng dụng? – bjan

Trả lời

1

Điều này khá "nhanh chóng và bẩn" nhưng tôi nghĩ nó mang lại kết quả chính xác.
tôi đã sử dụng một bảng pipelined nhưng có lẽ nó có thể được thực hiện mà không có nó ...

Here is a sqlfiddle demo

create table t1(id number, adr varchar2(120)) 
/
insert into t1 values(1, '152 Main st North Pole Factory 44, near the rear entrance cross the street and turn left and keep walking straight.') 
/
insert into t1 values(2, '122 Main st Pole Factory 44, near the rear entrance cross the street and turn left and keep walking straight. asdsa') 
/

create or replace type t is object(id number, phrase1 varchar2(40), phrase2 varchar2(40), phrase3 varchar2(40)) 
/
create or replace type t_tab as table of t 
/

create or replace function split_string(id number, str in varchar2) return t_tab 
    pipelined is 

    v_token varchar2(40); 
    v_token_i number := 0; 
    v_cur_len number := 0; 
    v_res_str varchar2(121) := str || ' '; 
    v_p1  varchar2(40); 
    v_p2  varchar2(40); 
    v_p3  varchar2(40); 
    v_p_i  number := 1; 

begin 

    v_token_i := instr(v_res_str, ' '); 

    while v_token_i > 0 loop 

    v_token := substr(v_res_str, 1, v_token_i - 1); 

     if v_cur_len + length(v_token) < 40 then 

     if v_p_i = 1 then 
      v_p1 := v_p1 || ' ' || v_token; 
     elsif v_p_i = 2 then 
      v_p2 := v_p2 || ' ' || v_token; 
     elsif v_p_i = 3 then 
      v_p3 := v_p3 || ' ' || v_token; 
     end if; 

     v_cur_len := v_cur_len + length(v_token) +1; 
    else 
     v_p_i := v_p_i + 1; 

     if v_p_i = 2 then 
      v_p2 := v_p2 || ' ' || v_token; 
     elsif v_p_i = 3 then 
      v_p3 := v_p3 || ' ' || v_token; 
     end if; 

     v_cur_len := length(v_token); 

    end if; 

    v_res_str := substr(v_res_str, v_token_i + 1); 
    v_token_i := instr(v_res_str, ' '); 

    end loop; 

    pipe row(t(id, v_p1, v_p2, v_p3)); 
    return; 
end split_string; 
/

Và truy vấn:

select parts.*, length(PHRASE1), length(PHRASE2), length(PHRASE3) 
from t1, table(split_string(t1.id, t1.adr)) parts 
+0

@ D.L, Rất tiếc, đã quên trường hợp từ cuối cùng (nơi không có không gian) đã cập nhật câu trả lời của tôi. (BTW, có một cách khác để sửa chữa nó - bạn có thể khởi tạo 'v_res_str varchar2 (120): = str || '';' –

+0

@DL, ý của bạn là gì * trên bay *? Bạn có thể sử dụng truy vấn được đề xuất dạng xem (có thể không có độ dài trường ...) –

+0

@D.L, tôi vẫn không thấy vấn đề - bạn cũng có thể thêm bất kỳ cột nào khác. Xem ví dụ này http://www.sqlfiddle.com/#!4/eeb18/1 –

2

Bạn có thể sử dụng đệ quy subquery bao thanh toán (CTE đệ quy):

with s (street_address, line, part_address, remaining) as (
    select street_address, 0 as line, 
    null as part_address, street_address as remaining 
    from address 
    union all 
    select street_address, line + 1 as line, 
    case when length(remaining) <= 40 then remaining else 
     substr(remaining, 1, instr(substr(remaining, 1, 40), ' ', -1, 1)) end 
     as part_address, 
    case when length(remaining) <= 40 then null else 
     substr(remaining, instr(substr(remaining, 1, 40), ' ', -1, 1) + 1) end 
     as remaining 
    from s 
) 
cycle remaining set is_cycle to 'Y' default 'N' 
select line, part_address 
from s 
where part_address is not null 
order by street_address, line; 

Sở thích nào h dữ liệu của bạn cho:

 LINE PART_ADDRESS       
---------- ---------------------------------------- 
     1 152 Main st North Pole Factory 44, near 
     2 the rear entrance cross the street and 
     3 turn left and keep walking straight.  

SQL Fiddle demo với hai địa chỉ.

Bạn cũng có thể chuyển đổi các giá trị một phần thành các cột mà tôi nghĩ là mục tiêu cuối cùng của bạn, ví dụ: dưới dạng xem:

create or replace view v_address as 
with cte (street_address, line, part_address, remaining) as (
    select street_address, 0 as line, 
    null as part_address, street_address as remaining 
    from address 
    union all 
    select street_address, line + 1 as line, 
    case when length(remaining) <= 40 then remaining else 
     substr(remaining, 1, instr(substr(remaining, 1, 40), ' ', -1, 1)) end 
     as part_address, 
    case when length(remaining) <= 40 then null else 
     substr(remaining, instr(substr(remaining, 1, 40), ' ', -1, 1) + 1) end 
     as remaining 
    from cte 
) 
cycle remaining set is_cycle to 'Y' default 'N' 
select street_address, 
    cast (max(case when line = 1 then part_address end) as varchar2(40)) 
    as address_1, 
    cast (max(case when line = 2 then part_address end) as varchar2(40)) 
    as address_2, 
    cast (max(case when line = 3 then part_address end) as varchar2(40)) 
    as address_3 
from cte 
where part_address is not null 
group by street_address; 

Another SQL Fiddle. Có thể cần lưu ý rằng nếu chiều dài street_address gần 120 ký tự, nó có thể không vừa gọn gàng thành 3 khối 40 ký tự - bạn sẽ mất một số ký tự tùy thuộc vào độ dài của từ được bao bọc cho 'dòng' kế tiếp . Cách tiếp cận này sẽ tạo ra nhiều hơn 3 dòng, nhưng chế độ xem chỉ sử dụng ba dòng đầu tiên, vì vậy bạn có thể mất phần cuối của địa chỉ. Bạn có thể muốn tạo các trường dài hơn hoặc có address_4 cho các trường hợp đó ...

Các vấn đề liên quan