2015-04-07 36 views
0

嘿,我想創建一個隨機數。當這個隨機數已經存在時,我想一次又一次地調用randomnumber函數。在這種情況下,我需要返回CASE WHEN語句中的randomnumber函數。 它不起作用。仍然會出現該號碼已經存在的錯誤。我想創建一個隨機數爲唯一的列:當無併發運行Postgres - 返回功能的情況下,當聲明

CREATE OR REPLACE FUNCTION getrandomnumber(integer, integer) 
     RETURNS integer AS 
     $BODY$ 
     DECLARE 
      start_int ALIAS FOR $1; 
      end_int ALIAS FOR $2; 
      name int; 
     BEGIN 
     name = trunc(random() * (end_int-start_int) + start_int); 

     CASE WHEN (select count(alias) from drivers where alias = name limit 1) = 0 

     THEN RETURN name; 

     ELSE RETURN getrandomnumber(start_int, end_int); 

     END CASE; 
     END; 

     $BODY$ 

     LANGUAGE plpgsql VOLATILE STRICT 
     COST 100; 
     ALTER FUNCTION getrandomnumber(integer, integer) 
     OWNER TO postgres; 
+0

顯示錶結構和樣本數據 –

+0

表包含一個id,一個名稱和一個別名。 Id是通過Sequenzce創建的,name是一個varchar,別名是1到1000之間的bigint。這個別名我想通過函數創建。別名列是唯一的。 – Pauli

回答

0

你的功能才能正常工作對我來說,即由一個用戶的時間。

有了:

CREATE TABLE drivers (alias integer); 

INSERT INTO drivers(alias) VALUES (1),(2); 

CREATE OR REPLACE FUNCTION ...; 

然後

INSERT INTO drivers(alias) VALUES (getrandomnumber(1, 5)); 

工作兩次,然後失敗,無限遞歸。


如果在多個會話中同時調用它,則您的函數將無法正常工作。您必須LOCK TABLE drivers IN EXCLUSIVE MODE或準備好處理唯一的違規錯誤。

我認爲你真正想要的東西更像是一個不重複的「隨機序列」,例如, the pseudo-encrypt function


順便說一句,雖然:

(select count(alias) from drivers where alias = name limit 1) = 0 

會的工作,你或許應該嘗試:

exists (select 1 from drivers where alias = name limit 1) 

,因爲它通常更快的。

+0

有沒有辦法使用我的功能? – Pauli

+0

@Pauli您的功能需要更改爲使用「IF ... THEN ... END IF」而不是「CASE ... WHEN ... END」。否則,它會起作用,它不是一個很好的方式來做我認爲你實際上想要做的事情,並且它不會在併發下工作。如果你想生成「隨機」但唯一的數字,使用上面鏈接的僞加密函數,它會好得多。 –

+0

好吧,我可以使用這個僞加密函數,但我還沒有unqiue隨機數。我仍然必須使用IF ... THEN .... END IF如果部分出於我的功能?我怎樣才能把輸出減少到6?我需要一個介於1和999999之間的隨機數。 – Pauli