2012-08-27 74 views
4

如何使用Postgresql 8.4,如何正確填充空白的字符串而不是當它太長時截斷它?使用rpad在Postgresql中填充字符串而不截斷

問題是,rpad截斷該字符串實際上比要填充的字符數更長。例如:

SELECT rpad('foo', 5); ==> 'foo ' -- fine 
SELECT rpad('foo', 2); ==> 'fo' -- not good, I want 'foo' instead. 

我發現的最短的解決方案並不涉及rpad都:

SELECT 'foo' || repeat(' ', 5-length('foo')); ==> 'foo ' -- fine 
SELECT 'foo' || repeat(' ', 2-length('foo')); ==> 'foo' -- fine, too 

但是這看起來醜陋恕我直言。請注意,我不實際選擇過程中的字符串「富」,而不是我從一列選擇:

SELECT colname || repeat(' ', 30-length(colname)) FROM mytable WHERE ... 

是否有一個更優雅的解決方案?

回答

6

發現了一個稍微更優雅的解決方案:

SELECT greatest(colname,rpad(colname, 2)); 

如:

SELECT greatest('foo',rpad('foo', 5)); -- 'foo ' 
SELECT greatest('foo',rpad('foo', 2)); -- 'foo' 


爲了解釋它的工作原理: RPAD( '富',5)= '富',這是> '富'(最大作品與字符串以及數字) RPAD( '富',2 )='fo',它是<'foo',所以'foo'被最大的功能選中。

如果您想要左填充的詞不能用得最多,因爲它比較從左到右(例如'oo'和'foo'),並且在某些情況下,根據字符串的不同,這可能會更大或更小。我想你可以扭轉字符串並使用rpad並將其逆轉回來,或者只是使用在兩種情況下都可用的原始解決方案。

+1

看起來不錯。謝謝! – dmoebius

+1

不幸的是,它不適用於lpad,在這種情況下,你將不得不使用不太優雅的解決方案;) – TimoSolo

+0

@Timothy:你能解釋爲什麼它不適用於lpad嗎? – Michael

6

如果你不想一直寫這業務,只需編寫自己的函數。事情是這樣的:

create or replace function rpad_upto(text, int) returns text as $$ 
begin 
    if length($1) >= $2 then 
     return $1; 
    end if; 
    return rpad($1, $2); 
end; 
$$ language plpgsql; 

或本:

create or replace function rpad_upto(text, int) returns text as $$ 
select $1 || repeat(' ', $2 - length($1)); 
$$ language sql; 

然後你可以說這樣的話:

select rpad_upto(colname, 30) from mytable ... 

你可能要考慮你想要什麼rpad_upto(null, n)生產,而你在它。如果$1爲NULL,則上面兩個版本的rpad_upto都會返回NULL,但您可以調整它們以便毫無困難地返回其他內容。

+0

感謝您的回答。它會工作,但數據庫管理員不允許我創建新的功能(至少不是這樣一個微不足道的任務,只有當絕對必要時)。 – dmoebius

3

這個怎麼樣

select case when length(col) < x then rpad(col, x) 
else col 
end 
from table 
+1

不錯,但比我的8個字更好。 ;) – dmoebius

0

假設效率是不是你最關心的問題在這裏:

select regexp_replace(format('%5s', 'foo'), '(\s*)(\S*)', '\2\1') 
  1. 格式()左墊串所需寬度
  2. 然後REGEXP_REPLACE移動任何前導空格到底。

我想這會失敗,如果你有字符串中的前導空格,並且你想保留它們。另請注意,format()在null參數上不返回null。