2009-06-16 106 views
12

是否有與以下內容等同的或替代的內容?Oracle'printf'等效

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

Oracle有類似printf樣式格式的東西嗎?

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

(str_a ||''|| str_b)或上面用括號括起來的字符串的語法看起來很難看(對於代碼)並且難以閱讀。它似乎應該有一個更優雅的方式。 – Steven 2009-06-16 17:51:04

+0

另一個解決方案是編寫一個需要參數的pl/sql包,並按照您希望的方式對其進行格式化。 – EvilTeach 2009-06-16 20:26:17

+0

不幸的是,PL/SQL不支持函數的變量數量和類型參數 - 最接近的方法是實現函數printf(t varchar2,v1 varchar2:= null,v2 varchar2:= null,v3 varchar2:= null,v4 varchar2:= null,v5 varchar2:= null)RETURN VARCHAR2(如果需要,可添加其他varchar2參數)。雖然我會考慮重命名它,因爲printf的目的是將結果發送到stdout,而在這裏您只希望它返回結果字符串。 – 2009-06-17 01:19:23

回答

6

不,沒有內置的Oracle函數以這種方式應用格式化字符串。儘管爲這個特定的例子編寫一個自定義函數會很容易,但編寫一個基於PL/SQL的printf實現會很有挑戰性。

如果你經常需要這個,也許你可以編寫一個Oracle函數來包裝一個Java調用,以獲得更豐富的字符串處理環境。

+0

現在這是一個古老的答案,但你知道這是否仍然如此? – flindeberg 2014-12-01 08:52:39

1

您可以在select中解決它。

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

你也應該看看功能

to_char

to_date

to_number

,因爲它們提供了更好的粒度來表達你想要的東西。

3

又一個主意,你:我發現更換待了這種事情,特別是當模板是複雜的有用:

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 

唯一的缺點是你需要添加儘可能多的REPLACE(「因爲有變量需要替換 - 但是至少你只需要每個變量都有一個變量,而不管它在模板中出現多少次。

(注:還有就是要使用「%」作爲分隔符,沒有特別的意義,它是我的只是個人的約定 - 你可以選擇不同的模式,如<mix_type>[mix_type]

對於這個特定的比如,它看起來像矯枉過正,但在某些情況下,它可以使事情變得更加簡單,例如:

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

比較上面:

output := 'bla bla ' || some_complex_expression || ' ' || b || ' ' || some_complex_expression; 
16

對於Oracle而言,我認爲最接近printf的標準是utl_lms.format_message。但是,它不會在SQL語句的工作,那就是,這是確定:

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

但是這給出了一個ORA-00902:無效的數據類型錯誤:

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

我做適用於Oracle SQL/PLSQL的簡單模板引擎ora_te (on GitHub)。 有了它的幫助下你的目標可以通過以下方式來實現:

無效藥實現與模板字符串的多個parsings:

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; 

有效地執行一個時間編譯(解析):

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; 

順便說一句,它還支持命名佔位符。