2017-11-22 1 views
0

1000000から4294967295までの範囲で未使用の一意のIDを生成するSQL関数を記述しようとしましたが、UUID()も解決策ではありません。それは難しいとは言えませんが、何らかの理由で、プライマリキーの値としてテーブルのINSERTステートメント内で呼び出された場合、以下のコードは機能しません(auto_incrementではなく)。ステートメントは、(デフォルト値がこのような機能に許可されていないので、私はすぐに各引数に0を送信して所望の値に関数で設定。)INSERT INTO table (id, content) VALUES ((SELECT getRandomID(0,0)), 'blabla bla'); ようなもので一度INSERTやPythonコードから分離呼び出さMySQL:ランダムなユニークな整数のIDを取得

、 すべて順調。何度か呼び出されると、何か不思議なことが起こり、プロセス全体だけでなく、サーバーもREPEATの中にハングアップする可能性があります。プロセスはkill/restartを実行することさえできません。私はマシンを再起動する必要があります.- 同じ値がいくつかの呼び出しの後に何度も何度も出現するので、いくつかのランダムな値しか用意されていないようです。実際には内部が十分に開始/外側はrand()です。 Pythonから呼び出されたループはいくつかのラウンド後にハングアップしますが、テストの最初のものは常に有用な新しいIDを生成するため、最初のラウンド後に終了する必要があります。ワイ?まあ、テーブルは空です...だからSELECT COUNT(*)...は実際にループを離れるための信号ですが、0を返します...しかしそれはありません。

アイデア? SLES 12.2でMariaDB 10.somethingを実行しています。ここでエクスポートしたソースコードは次のとおりです。

DELIMITER $$ 
CREATE DEFINER=`root`@`localhost` FUNCTION `getRandomID`(`rangeStart` BIGINT UNSIGNED, `rangeEnd` BIGINT UNSIGNED) RETURNS bigint(20) unsigned 
READS SQL DATA 
BEGIN 
    DECLARE rnd BIGINT unsigned; 
    DECLARE i BIGINT unsigned; 

    IF rangeStart is null OR rangeStart < 1 THEN 
     SET rangeStart = 1000000; 
    END IF; 
    IF rangeEnd is null OR rangeEnd < 1 THEN 
     SET rangeEnd = 4294967295; 
    END IF; 

    SET i = 0; 

    r: REPEAT 
     SET rnd = FLOOR(rangeStart + RAND(RAND(FLOOR(1 + rand() * 1000000000))*10) * (rangeEnd - rangeStart)); 
     SELECT COUNT(*) INTO i FROM `table` WHERE `id` = rnd;  
    UNTIL i = 0 END REPEAT r; 

    RETURN rnd; 
END$$ 
DELIMITER ; 

答えて

0

若干の改善:

SELECT COUNT(*) INTO i FROM `table` WHERE `id` = rnd;  
UNTIL i = 0 END REPEAT r; 

- >

UNTIL NOT EXISTS(SELECT 1 FROM `table` WHERE id = rnd) REPEAT r; 

RANDに任意の引数を渡してはいけない - それが確立するためです反復可能な乱数列。

mysql> SELECT RAND(123), RAND(123), RAND(), RAND()\G 
*************************** 1. row *************************** 
RAND(123): 0.9277428611440052 
RAND(123): 0.9277428611440052 
    RAND(): 0.5645420109522921 
    RAND(): 0.12561983719991504 
1 row in set (0.00 sec) 

あなたは1を追加し、可能な出力でrangeEndを含めたい場合はそう

SET rnd = FLOOR(rangeStart + RAND() * (rangeEnd - rangeStart)); 

に簡素化:

SET rnd = FLOOR(rangeStart + RAND() * (rangeEnd - rangeStart + 1)); 
+0

おかげでたくさん!関数に変更を適用する際に間違いを犯した後、すべてが正常に機能しています。多分RAND()の議論の前に掛かっていたからでしょうか?または何か他の魔法があります。 > 1000ラウンドになりました。 – meistermuh

関連する問題