2015-04-07 57 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