随机唯一整数避免在插入之前重复

时间:2018-11-02 03:49:12

标签: sqlite

鉴于需要存储4位随机唯一整数,我将如何高效地插入大量高质量的新数字。

如果这些值是在sqlite外部创建的,则有可能该值已经存在于数据库中

完成这项任务的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

您可以使要存储数字的列唯一,并在具有多个值的单插入中使用INSERT或IGNORE(以提高效率)。例如:-

INSERT OR IGNORE INTO rndm_id VALUES
  ('0001'),('0027'),('9999'),('0412'),('2108'),
  ('0001'), -- duplicate will be skipped
  ('3085') -- and so on
;

注释值已包含在引号中,以维护4个数字。该表是使用:-

定义的
CREATE TABLE IF NOT EXISTS rndm_id (myid TEXT UNIQUE);

如果您考虑大量值,则可能需要考虑:-

  

SQL语句的最大长度

     

SQL语句文本中的最大字节数受到限制   设置为SQLITE_MAX_SQL_LENGTH,默认值为1000000。您可以重新定义   此限制与SQLITE_MAX_LENGTH中的较小者一样大,并且   1073741824。

     

如果SQL语句的长度限制为一百万个字节,则   显然,您将无法通过插入几百万个字节的字符串   将它们作为文字嵌入INSERT语句中。但是你应该   无论如何不要这样做。对数据使用主机参数。准备短片   这样的SQL语句:

     

INSERT INTO tab1 VALUES(?,?,?);然后使用sqlite3_bind_XXXX()   函数将大字符串值绑定到SQL语句。的   使用绑定消除了在转义符中转义引号字符的需要   字符串,降低SQL注入攻击的风险。它也运行   更快,因为不需要将大字符串解析或复制为   很多。

     

SQL语句的最大长度可以在运行时降低   使用sqlite3_limit(db,SQLITE_LIMIT_SQL_LENGTH,size)接口。   Limits In SQLite

考虑评论

  

有没有办法我可以选择一组新值呢?   可以使用,然后稍后插入?

因此,假设您需要1000个4位数的唯一随机值,则以下内容就足够了:-

DROP TABLE IF EXISTS save_for_later; -- Drop the table
CREATE TEMP TABLE IF NOT EXISTS save_for_later (four_digit_random_value UNIQUE); -- Create a temporary table

-- Create a table with 1500 random rows 
WITH RECURSIVE cte1 AS (
    SELECT CAST((abs(random() % 10)||abs(random() % 10)||abs(random() % 10)||abs(random() % 10)) AS TEXT)
    UNION ALL SELECT CAST((abs(random() % 10)||abs(random() % 10)||abs(random() % 10)||abs(random() % 10)) AS TEXT)
    FROM cte1 LIMIT 1500
    )
INSERT OR IGNORE INTO save_for_later SELECT * FROM cte1;

-- Later on extract the 1000 required rows.
SELECT * FROM save_for_later LIMIT 1000;

可疑要求

如果问题是 我如何才能将具有随机数据的一组固定数量(300)4个数字唯一值插入到具有现有数据的表(主数据)中,新值也应与现有值

然后,以下方法可以做到这一点(请参阅注释限制):-

DROP TABLE IF EXISTS master; -- 
CREATE TABLE IF NOT EXISTS master (random_value TEXT UNIQUE);

-- Master (existing) Table populated with some values
INSERT OR IGNORE INTO master VALUES
  ('0001'),('0027'),('9999'),('0412'),('2108'),
  ('0001'), -- duplicate will be skipped
  ('3085') -- and so on
;
SELECT * FROM master; -- Result 1 show what's in the master table

-- Create a table to save the values for later
DROP TABLE IF EXISTS save_for_later; -- Drop the table
CREATE TEMP TABLE IF NOT EXISTS save_for_later (four_digit_random_value UNIQUE); -- Create a temporary table

-- Populate the vales to be saved for later excluding any values that already exist
-- 1500 rows perhaps excessive but very likely to result in 300 unique values
WITH RECURSIVE cte1(rndm) AS (
    SELECT 
        CAST((abs(random() % 10)||abs(random() % 10)||abs(random() % 10)||abs(random() % 10)) AS TEXT)
    UNION ALL 
    SELECT 
        CAST((abs(random() % 10)||abs(random() % 10)||abs(random() % 10)||abs(random() % 10)) AS TEXT) 
    FROM cte1 
    LIMIT 1500 --<<<<<< LIMIT important otherwise would be infinite
    )
    INSERT OR IGNORE INTO save_for_later 
        SELECT * FROM cte1 
            WHERE rndm NOT IN(SELECT * FROM master)
;

-- Later on extract the required rows (300 here) and insert them.
INSERT INTO master
    SELECT * FROM save_for_later 
    LIMIT 300;

SELECT * FROM master; -- Should be 6 original/existing rows + 300 so 306 rows (although perhaps a chance that 300 weren't generated)
  • 请注意,如果使用4个数字,则限制为10,000个可能的值(0000-9999),因此,原始表中存在的值越多,查找唯一值的可能性就越大。

以上将导致:-

第一个结果是生成新值之前的主表:-

enter image description here

添加新值(原始6行+新300行)后的结果:-

enter image description here