MySql 5.5.37を使用しています。次の列を持つテーブルがあります
+------------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------+-------+
| ID | varchar(32) | NO | PRI | NULL | |
| CODE | varchar(6) | NO | UNI | NULL | |
コード列は一意であり、ID列はGUIDです。上記の表のいくつかの基準(WHERE COLUMN1 = 0など)に従って、更新したい行がいくつかあります。 CODE列のランダムな一意の6文字コード(理想的には文字と数字)を生成して、テーブルの一意制約に違反しないようにするにはどうすればよいですか?条件を満たさないテーブルの列(例:COLUMN1 <> 0)には、既にCODE列の一意の値があります。
編集: これはこの質問とは異なります- MySQL を使用してランダムで一意の8文字の文字列を生成するのは、そのリンクがIDを処理するためです。私のIDは32文字の文字列です。また、それらのソリューションは、実行したいステートメントを実行する前にテーブルに値があり、問題の列に一意の値を生成するという事実を考慮していません。
更新前のトリガーソリューション:
以下を使用して、6文字のランダムな英数字の大文字ストリングを作成できます。
lpad(conv(floor(Rand()*pow(36,6)), 10, 36), 6, 0);
既存の文字列を作成しないために、BEFORE UPDATE
トリガーを使用できます。
DELIMITER //
CREATE TRIGGER `unique_codes_before_update`
BEFORE UPDATE ON `unique_codes` FOR EACH ROW
BEGIN
declare ready int default 0;
declare rnd_str text;
if new.CODE is null then
while not ready do
set rnd_str := lpad(conv(floor(Rand()*pow(36,6)), 10, 36), 6, 0);
if not exists (select * from unique_codes where CODE = rnd_str) then
set new.CODE = rnd_str;
set ready := 1;
end if;
end while;
end if;
END//
DELIMITER ;
CODE
ステートメントでNULL
列をUPDATE
に設定するたびに、トリガーはテーブル内で一致が見つからなくなるまでループ内に新しいランダム文字列を作成します。
これで、すべてのNULL値を次のものに置き換えることができます。
update unique_codes set CODE = NULL where code is NULL;
SQLFiddle demo here iでは、1文字のランダムな文字列を使用して、値が重複していないことを示します。
BEFORE INSERT
トリガーで同じコードを使用することもできます。この方法では、CODE=NULL
を使用して新しい行を挿入するだけで、トリガーはそれを新しい一意のランダムな文字列に設定します。また、再度更新する必要はありません。
元の回答(32文字の文字列):
select lpad(conv(floor(Rand()*pow(36,8)), 10, 36), 8, 0) as rnd_str_8;
-- output example: 3AHX44TF
8文字の英数字の大文字のランダム文字列を生成します。 4つを連結して32文字を取得します。
select concat(
lpad(conv(floor(Rand()*pow(36,8)), 10, 36), 8, 0),
lpad(conv(floor(Rand()*pow(36,8)), 10, 36), 8, 0),
lpad(conv(floor(Rand()*pow(36,8)), 10, 36), 8, 0),
lpad(conv(floor(Rand()*pow(36,8)), 10, 36), 8, 0)
) as rnd_str_32;
-- output example: KGC8A8EGKE7E4MGD4M09U9YWXVF6VDDS
http://sqlfiddle.com/#!9/9eecb7d/769
では、均一性はどうでしょうか?まあ-複製を生成してみてください;-)
CONV(CONV(( SELECT MAX(CODE) FROM tbl ), 36, 10) + 1, 10, 36)
base-36(数字と大文字)でエンコードされた次の「番号」を取得します。
例えば:
SELECT CONV(CONV(( 'A1B2C' ), 36, 10) + 1, 10, 36); --> 'A1B2D'
DELIMITER $$
USE `db` $$
DROP PROCEDURE IF EXISTS `GenerateUniqueValue`$$
CREATE PROCEDURE `GenerateUniqueValue`(IN tableName VARCHAR(255),IN columnName VARCHAR(255))
BEGIN
DECLARE uniqueValue VARCHAR(8) DEFAULT "";
WHILE LENGTH(uniqueValue) = 0 DO
SELECT CONCAT(SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1)
) INTO @newUniqueValue;
SET @rcount = -1;
SET @query=CONCAT('SELECT COUNT(*) INTO @rcount FROM ',tableName,' WHERE ',columnName,' like ''',@newUniqueValue,'''');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
IF @rcount = 0 THEN
SET uniqueValue = @newUniqueValue ;
END IF ;
END WHILE ;
SELECT uniqueValue;
END$$
DELIMITER ;
このストアドプロシージャを次のように呼び出します
Call GenerateUniqueValue('tableName','columnName')
これにより、一意の8文字の文字列が毎回提供されます。
これはトリッキーですが、ニースのソリューションに到達したと思います。
_DROP FUNCTION IF EXISTS getRandomAlphaNumeric;
DELIMITER $$
CREATE FUNCTION getRandomAlphaNumeric() RETURNS CHAR(6)
DETERMINISTIC
BEGIN
SELECT
CONCAT (
CHAR(FLOOR(Rand()*10)+48), CHAR(FLOOR(Rand()*26)+65), CHAR(FLOOR(Rand()*26)+97),
CHAR(FLOOR(Rand()*10)+48), CHAR(FLOOR(Rand()*26)+65), CHAR(FLOOR(Rand()*26)+97)
) INTO @code
;
RETURN @code;
END
$$
DELIMITER ;
DROP PROCEDURE IF EXISTS generateCodes;
DELIMITER $$
CREATE PROCEDURE generateCodes()
BEGIN
SET @count = 0;
SELECT COUNT(1) INTO @count FROM demo.codes;
SET @i = 0;
WHILE @i < @count DO
PREPARE stmt FROM "SELECT @id := id, @itemCode := code FROM demo.codes p LIMIT ?, 1;";
EXECUTE stmt USING @i;
SET @code = getRandomAlphaNumeric();
SELECT COUNT(1) INTO @countRowsWithCode FROM demo.codes WHERE code = @code;
IF @countRowsWithCode = 0 AND @itemCode IS NULL THEN
UPDATE demo.codes SET code = @code WHERE id = @id;
END IF;
SET @i := @i + 1;
END WHILE;
END
$$
DELIMITER ;
CALL generateCodes();
_
まず、目的のコードを生成するために使用される6文字のランダムな文字列を返す関数を作成しました。
_DROP FUNCTION IF EXISTS getRandomAlphaNumeric;
DELIMITER $$
CREATE FUNCTION getRandomAlphaNumeric() RETURNS CHAR(6)
DETERMINISTIC
BEGIN
SELECT
CONCAT (
CHAR(FLOOR(Rand()*10)+48), CHAR(FLOOR(Rand()*26)+65), CHAR(FLOOR(Rand()*26)+97),
CHAR(FLOOR(Rand()*10)+48), CHAR(FLOOR(Rand()*26)+65), CHAR(FLOOR(Rand()*26)+97)
) INTO @code
;
RETURN @code;
END
$$
_
次に、ランダムな一意のコードでテーブルを更新する手順を作成しました。手順は次のとおりです。
6文字の新しいランダムなコードで更新されるすべてのレコードをカウントします。
SELECT COUNT(1) INTO @count FROM demo.codes;
次に、foreach行(WHILE
ループを使用):
更新する次のレコードのIDを取得します
_PREPARE stmt FROM "SELECT @id := id, @itemCode := code FROM demo.codes p LIMIT ?, 1;";
_ _EXECUTE stmt USING @i;
_
レコードの新しいコードを取得します。
SET @code = getRandomAlphaNumeric();
最後に、新しいコードがテーブルにまだ存在していないか確認し、現在フィールド列に値がない(NULL
)、ない場合、現在のレコードを更新しますランダムコード:
SELECT COUNT(1) INTO @countRowsWithCode FROM demo.codes WHERE code = @code; IF @countRowsWithCode = 0 AND @itemCode IS NULL THEN UPDATE demo.codes SET code = @code WHERE id = @id; END IF;
最後に、CALL
であるPROCEDURE
列からフィールドにデータを入力するために、code
が作成されたNULL
になります。
CALL generateCodes();
コードでこれを試してください
_SELECT LEFT(MD5(NOW()), 6) AS CODE;
_
LEFT(MD5(NOW()), 6)
これは、6文字の一意のコードを返します。
このような別の方法を試してください
_SELECT LEFT(UUID(), 6);
_
LEFT(UUID(), 6)
これは一意のコードも返します