Received: from localhost (unknown [200.46.208.211]) by mail.postgresql.org (Postfix) with ESMTP id BF986632FF3 for ; Tue, 20 Oct 2009 17:04:06 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by localhost (mx1.hub.org [200.46.208.211]) (amavisd-maia, port 10024) with ESMTP id 32455-06 for ; Tue, 20 Oct 2009 20:03:52 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mail-px0-f199.google.com (mail-px0-f199.google.com [209.85.216.199]) by mail.postgresql.org (Postfix) with ESMTP id 8DE2363281A for ; Tue, 20 Oct 2009 17:03:55 -0300 (ADT) Received: by pxi37 with SMTP id 37so4268007pxi.15 for ; Tue, 20 Oct 2009 13:03:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:cc:subject:references:in-reply-to :content-type:content-transfer-encoding; bh=6DzPnt7DxqHrxFmkGk6aKW7lcy2odgFbJZQGAEYFl38=; b=fgU7p+aXN3s8Jsdc6oPnamrSWzfaC6bTGvTfHTY5IKMq+dfS5Bxl86C3FMJMg7IXuc DhaSGT8J3bTkDYMwLelyIMLGRCeMHf22hVRhhaAa8d9z6ePMbnfoF6+Toix3tCkr7eJR S/+srEgjlKb18QCeicKXsL0HNGAibcLN9akSQ= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:content-type:content-transfer-encoding; b=LnH+w5p27tZ/JZbtFZejK7XrNusQVu85WVCMTg5hGmI+8sehKl7S8hU2ulvSToisU2 VLLREtzPrQ+YGA94p3IyyLtaXBChTVLbvD9lREHgV+IjUIS7iRaHOcscEBhHJW15LtFk tQsCKvdyAmKeT+Qa8XUj47Ri+x45nK4/TfIHM= Received: by 10.114.2.12 with SMTP id 12mr10091258wab.52.1256069034151; Tue, 20 Oct 2009 13:03:54 -0700 (PDT) Received: from ?172.16.1.239? ([208.187.158.94]) by mx.google.com with ESMTPS id 22sm250468pzk.6.2009.10.20.13.03.52 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 20 Oct 2009 13:03:53 -0700 (PDT) Message-ID: <4ADE17A2.6010003@gmail.com> Date: Tue, 20 Oct 2009 14:03:46 -0600 From: Rob Sargent User-Agent: Thunderbird 2.0.0.23 (X11/20090817) MIME-Version: 1.0 To: Nahuel Alejandro Ramos CC: pgsql-sql@postgresql.org Subject: Re: Random Unique Id References: <80df75370910201249k40e308dbh668872e0e2ed2419@mail.gmail.com> <4ADE1520.5080203@gmail.com> <80df75370910201257m2d64ad7tad0636f9b664bdeb@mail.gmail.com> In-Reply-To: <80df75370910201257m2d64ad7tad0636f9b664bdeb@mail.gmail.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-2.181 tagged_above=-10 required=5 tests=AWL=0.419, BAYES_00=-2.599 X-Spam-Level: X-Archive-Number: 200910/81 X-Sequence-Number: 33280 Suit yourself, of course, but the numbers on my credit cards are far, far from random :) Nahuel Alejandro Ramos wrote: > Yes. I looked this solution but it is not a "only numbers" ID. I would > like a random unique "number" Id. For example: generate a credit number > randomly (like the example I post). > I used to insert an MD5 field but this time I need "only numbers" Id. > Regards... > > Nahuel Alejandro Ramos. > > > On Tue, Oct 20, 2009 at 4:53 PM, Rob Sargent > wrote: > > > > Nahuel Alejandro Ramos wrote: > > Hi all, > > I was searching for a sequence (for serials) that let me use a > random > > unique number ID on a Primary Key or a simple index. > > I have not found a solution so I have done it by myself. I would > like > > to share it so here it is: > > > > -- ---------------------------- > > -- Create language "plpgsql" > > -- ---------------------------- > > CREATE LANGUAGE plpgsql; > > > > -- ---------------------------- > > -- Table structure for "public"."tarjeta" > > -- ---------------------------- > > drop table "public"."tarjeta"; > > CREATE TABLE "public"."tarjeta"( > > "idtarjeta" int8 NOT NULL DEFAULT randomuniqueidtarjeta(), > > "fechaemision" timestamp NOT NULL DEFAULT now(), > > "descripcion" varchar(255) , > > PRIMARY KEY ("idtarjeta") > > ) WITHOUT OIDS; > > > > -- ---------------------------- > > -- Definition of function "randomuniqueidtarjeta" > > -- ---------------------------- > > > > CREATE OR REPLACE FUNCTION randomUniqueIdTarjeta() RETURNS bigint > AS $$ > > > > DECLARE > > > > -- SET THE KEY SIZE (IN CHARACTERS) > > idSize constant integer := 10; > > > > sizeMultiplicator constant bigint := 10 ^ idSize; > > > > loopLimit bigint := sizeMultiplicator * 4; > > randomNumber bigint; > > canIUseIt boolean := false; > > > > BEGIN > > > > -- LOOP UNTIL FIND AN UNIQUE RANDOM NUMBER OR FILL THE LOOP LIMIT > > WHILE ( not ( canIUseIt ) and ( loopLimit > 0) ) LOOP > > > > -- CALCULATE A TEN DIGITS RANDOM NUMBER > > randomNumber := CAST ( ( random() * sizeMultiplicator ) AS > bigint ); > > > > -- VALIDATE THAT THE NUMBER WON'T START WITH 0 > > IF ( (randomNumber >= sizeMultiplicator / 10 ) and ( > > randomNumber < sizeMultiplicator ) ) THEN > > > > -- CHECK THAN RANDOM NUMBER NOT EXISTS ON TABLE > > -- IMPORTANT!!! CHANGE WITH TABLE AND FIELD TO SEARCH > FOR A > > DUPLICATATION > > PERFORM idtarjeta FROM tarjeta WHERE idtarjeta = > randomNumber; > > IF NOT FOUND THEN > > canIUseIt = true; > > END IF; > > > > END IF; > > > > loopLimit = loopLimit - 1; > > > > END LOOP; > > > > -- IF LOOP ENDS WITH A UNIQUE RANDOM NUMBER RETURNS THE NUMBER > > CONCATENATED WITH A VERIFICATION NUMBER ELSE RAISE AN EXCEPTION > > IF ( canIUseIt ) THEN > > RETURN CAST ( ( CAST ( randomNumber AS text ) || CAST ( > > verificationNumber( CAST (randomNumber AS text ) ) AS text ) ) AS > > bigint ) ; > > ELSE > > RAISE EXCEPTION 'Could not calculate a Random Unique ID on > table > > Tarjeta.'; > > END IF; > > > > END; > > $$ LANGUAGE plpgsql; > > > > -- ---------------------------- > > -- Definition of function "randomuniqueidtarjeta" > > -- ---------------------------- > > > > CREATE OR REPLACE FUNCTION verificationNumber(id text) RETURNS > integer AS $$ > > DECLARE > > > > auxValue integer := 0; > > verifyArray constant integer[] :=ARRAY [5,4,3,2,7,6,5,4,3,2,1]; > > verificationNumber integer := 0; > > > > BEGIN > > > > -- ASK FOR ID LENGTH EQUAL TO 10 DIGITS. THE ALGORITHM WORKS > ONLY FOR > > IF ( LENGTH( id ) <> 10 ) THEN > > > > RAISE EXCEPTION 'Could not calculate a verification > number. The > > ID must have 10 digits.'; > > > > ELSE > > > > -- LOOP ON THE TEN DIGITS AND MULTIPLY WITH THE SAME > POSITION ON > > virifyArray > > FOR digit IN 1..10 LOOP > > auxValue = auxValue + ( CAST(SUBSTR(id, digit, 1) AS > int) * > > verifyArray[digit] ); > > END LOOP; > > > > -- CALCULATE THE VERIFICATION NUMBER > > verificationNumber = 11 - (auxValue % 11); > > > > -- REPLACE THE TWO DIGITS VERIFICATION NUMBER > > IF( verificationNumber = 11 ) THEN > > RETURN 0; > > ELSEIF ( verificationNumber = 10 ) THEN > > RETURN 9; > > ELSE > > RETURN verificationNumber; > > END IF; > > > > END IF; > > > > END; > > $$ LANGUAGE plpgsql; > > > > -- ---------------------------- > > -- INSERTs to probe the functions > > -- ---------------------------- > > INSERT INTO tarjeta (descripcion) VALUES ('Tarjeta 1'); > > INSERT INTO tarjeta (descripcion) VALUES ('Tarjeta 2'); > > INSERT INTO tarjeta (descripcion) VALUES ('Tarjeta 3'); > > INSERT INTO tarjeta (descripcion) VALUES ('Tarjeta 4'); > > INSERT INTO tarjeta (descripcion) VALUES ('Tarjeta 5'); > > INSERT INTO tarjeta (descripcion) VALUES ('Tarjeta 6'); > > INSERT INTO tarjeta (descripcion) VALUES ('Tarjeta 7'); > > INSERT INTO tarjeta (descripcion) VALUES ('Tarjeta 8'); > > INSERT INTO tarjeta (descripcion) VALUES ('Tarjeta 9'); > > INSERT INTO tarjeta (descripcion) VALUES ('Tarjeta 10'); > > > > > > It is my first post so sorry about the format of the SQL > Dump and > > sorry about my english. > > Note: there is a second function that calculate a verification > > number like an argentinian code called CUIL (only available for 10 > > digits numbers) > > Regards.... > > > > Nahuel Alejandro Ramos. > > > > You didn't like UUID? > >