2009-06-16 34 views
12

Có tương đương hoặc thay thế cho những điều sau đây không?Oracle 'printf' tương đương

SELECT mix_type || ' (' || mix_num || ')' as description 
    FROM acid_batch 
WHERE mix_num < 10 

Oracle có định dạng kiểu printf không?

SELECT printf("%s (%s)", mix_type, mix_num) as description, 
    FROM acid_batch 
WHERE mix_num < 10 
+2

Cú pháp của (str_a || '' || str_b) hoặc trên để bao quanh một chuỗi có dấu ngoặc đơn có vẻ xấu xí (đối với mã) và khó đọc. Nó chỉ có vẻ như nên có một cách thanh lịch hơn. – Steven

+0

Một giải pháp khác là viết một gói pl/sql có các đối số và định dạng mọi thứ theo cách bạn muốn. – EvilTeach

+0

Thật không may PL/SQL không (chưa) hỗ trợ số lượng biến và các loại tham số cho một chức năng - cách gần nhất sẽ được thực hiện FUNCTION printf (t varchar2, v1 varchar2: = null, v2 varchar2: = null, v3 varchar2: = null, v4 varchar2: = null, v5 varchar2: = null) RETURN VARCHAR2 (thêm các tham số varchar2 bổ sung nếu bạn cần chúng). Mặc dù tôi muốn xem xét đổi tên nó vì mục đích của printf là gửi kết quả đến stdout, trong khi ở đây bạn đang mong đợi nó chỉ đơn giản trả về chuỗi kết quả. –

Trả lời

6

Không có sẵn chức năng Oracle nào áp dụng chuỗi định dạng theo cách này. Mặc dù sẽ dễ dàng viết một hàm tùy chỉnh cho ví dụ cụ thể này, việc viết một bản in thực thi dựa trên PL/SQL sẽ là một thách thức.

Nếu bạn có nhu cầu thường xuyên về điều này, có lẽ bạn có thể viết một hàm Oracle kết thúc cuộc gọi Java cho môi trường xử lý chuỗi phong phú hơn.

+0

Bây giờ đây là một câu trả lời cũ, nhưng bạn có biết nếu điều này vẫn là trường hợp? – flindeberg

1

Bạn có thể giải quyết trong lựa chọn.

SELECT mix_type || '(' || mix_num || ')' as description, 
FROM acid_batch 
WHERE mix_num < 10 

bạn cũng nên xem xét các chức năng

to_char

to_date

to_number

khi chúng cung cấp cho bạn một chi tiết tốt hơn về cách bạn muốn những thứ đại diện.

3

Chỉ cần một ý tưởng dành cho bạn: Tôi đã tìm thấy REPLACE để thể hữu ích cho loại điều, đặc biệt là khi các mẫu phức tạp:

SELECT REPLACE(REPLACE(
     '%mix_type% (%mix_num%)' /*template*/ 
     ,'%mix_type%', mix_type) 
     ,'%mix_num%' , mix_num) as description, 
FROM acid_batch 
WHERE mix_num < 10 

Nhược điểm duy nhất là bạn cần phải thêm bao nhiêu REPLACE( ' Vì có các biến để thay thế - nhưng ít nhất bạn chỉ cần có một biến cho mỗi biến, bất kể số lần nó xuất hiện trong mẫu.

(Chú ý: Không có ý nghĩa đặc biệt với việc sử dụng "%" như một dấu phân cách, nó chỉ là một quy ước cá nhân của tôi - bạn có thể chọn một mô hình khác nhau, ví dụ như <mix_type> hoặc [mix_type])

Đối đặc biệt này Ví dụ có vẻ như quá mức cần thiết, nhưng trong một số trường hợp nó có thể làm cho mọi việc dễ dàng hơn nhiều, ví dụ:

template := 'bla bla %a% %b% %a%'; 
output := REPLACE(REPLACE(template 
    ,'%a%', some_complex_expression) 
    ,'%b%', b); 

So sánh trên với:

output := 'bla bla ' || some_complex_expression || ' ' || b || ' ' || some_complex_expression; 
+0

Không phải là một ý tưởng tồi, nhưng bạn có lẽ chỉ muốn làm điều này trên một mẫu nhỏ với vài biến. Lý do của tôi cho điều này là tôi nghĩ rằng REPLACE sẽ phân tích cú pháp mẫu một lần trước mỗi cuộc gọi, để có thể ăn cpu. – aglassman

+0

Nếu bạn đã có hàng ngàn biến, đã đồng ý. Tôi đã sử dụng điều này cho đến một chục biến không có tác động hiệu suất đáng kể. Nó không thực sự "phân tích" như vậy - thay thế là một thao tác chuỗi tương đối đơn giản. –

16

Gần đúng tiêu chuẩn gần nhất để printf cho Oracle tôi có thể nghĩ là utl_lms.format_message. Tuy nhiên, nó sẽ không làm việc trong câu lệnh SQL, có nghĩa là, đây là ok:

begin 
    dbms_output.put_line(
    utl_lms.format_message('hello %s, the number is %d', 'world', 42) 
); 
end; 
/

nhưng điều này mang lại một ORA-00.902: datatype không hợp lệ lỗi:

select utl_lms.format_message('hello %s, the number is %d', 'world', 42) 
    from dual 
+0

Tài liệu cho biết đây là thông báo lỗi ("* UTL_LMS truy xuất và định dạng thông báo lỗi bằng các ngôn ngữ khác nhau. *"). Bạn có biết nếu có bất kỳ vấn đề hoặc hạn chế nào với việc sử dụng nó cho các chuỗi bình thường không? Tài liệu này khá thưa thớt. –

+0

đây là cách tôi làm .. nhưng tất cả các parmaters phải là CHAR/VARCHAR .. tức là '' chọn utl_lms.format_message ('hello% s, số là% s', 'world', TO_CHAR (42)) từ dual'' – ShoeLace

2

Tôi đã thực hiện một công cụ tạo mẫu đơn giản có tên là ora_te (on GitHub) cho Oracle SQL/PLSQL. Với sự giúp đỡ của nó mục tiêu của bạn có thể đạt được theo các cách sau:

thực hiện Noneffective với nhiều parsings của mẫu chuỗi:

with acid_batch as (
    select rownum as mix_type, rownum + 2 as mix_num 
    from all_objects 
    where rownum < 10 
) 
-- 
SELECT pk_te.substitute('$1 ($2)', ty_p(mix_type, mix_num)) as description 
FROM acid_batch 
WHERE mix_num < 10; 

An thực hiện có hiệu quả với một thời gian biên dịch (phân tích):

with acid_batch as (
    select rownum as mix_type, rownum + 2 as mix_num 
    from all_objects 
    where rownum < 10 
), 
-- 
o as ( 
    select ty_te.compile_numbered('$1 ($2)') te from dual 
) 
SELECT pk_te.substitute(o.te, ty_p(mix_type, mix_num)) as description 
FROM acid_batch, o 
WHERE mix_num < 10; 

BTW cũng hỗ trợ trình giữ chỗ có tên.

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