如何生成自动增加UNIQUE文本ID

时间:2018-03-08 15:48:42

标签: sql sql-server tsql

我被赋予了一个任务来创建一个表,其中CustomerID必须是文本(Varchar),并且必须是唯一的。 我使用下面的示例(使用计算字段)创建了表。我被告知该表不应包含任何计算字段,而且CustomerID列的LEN不应超过varchar(14)

CREATE TABLE dbo.Customer(
    CustID INT IDENTITY(1,1) PRIMARY KEY,
    customerID AS CAST(CustID AS VARCHAR(200))+LEFT(CONVERT(varchar(255), NEWID()),8),
    LastName varchar(300),
    FirstName varchar(300)NOT NULL
);

如果我不使用计算字段,我怎么能用独特的cutomerID创建表?

ID的输出应该看起来像

19DA9C895
2341F6E59
3B713A0CD

它可以是字母或字母和数字的混合 感谢

5 个答案:

答案 0 :(得分:1)

您可以使用customer_id列的序列和默认值。序列值是一个整数,customer_id是一个字符串,但您可以使用类似customer_id

的表达式从序列值派生RIGHT('00000000000000' + CAST(NEXT VALUE FOR customer_id_seq AS varchar(14)), 14)

请运行以下代码以查看其工作原理:

use tempdb;
GO

CREATE SEQUENCE customer_id_seq START WITH 1 AS bigint;

GO

SELECT RIGHT('00000000000000' + CAST(NEXT VALUE FOR customer_id_seq AS varchar(14)), 14)

GO
CREATE TABLE customers
(
    customer_id varchar(14) DEFAULT (RIGHT('00000000000000' + CAST(NEXT VALUE FOR customer_id_seq AS varchar(14)), 14)),
    customer_name varchar(100) NOT NULL,
    CONSTRAINT pk_customers PRIMARY KEY(customer_id)
)

GO

INSERT INTO customers(customer_name) VALUES ('ACME');
INSERT INTO customers(customer_name) VALUES ('Marvel');

GO

INSERT INTO customers(customer_id, customer_name)
VALUES (RIGHT('00000000000000' + CAST(NEXT VALUE FOR customer_id_seq AS varchar(14)), 14), 'Fox');

INSERT INTO customers(customer_id, customer_name)
VALUES (RIGHT('00000000000000' + CAST(NEXT VALUE FOR customer_id_seq AS varchar(14)), 14), 'Columbia');

GO
SELECT * FROM customers

请注意,您可以插入新行而不指定customer_id列。但如果你愿意,你可以。如果您指定customer_id列,则应使用表达式RIGHT('00000000000000' + CAST(NEXT VALUE FOR customer_id_seq AS varchar(14)), 14)

编辑:

更好的选择是使用表达式CONVERT(varchar(14), CAST(NEXT VALUE FOR customer_id_seq AS varbinary(7)), 2)。因为customer_id域会更长,因为它不仅包含数字,还包含A,B,C,D和F字符。

表格如下:

CREATE TABLE customers
(
    customer_id varchar(14) DEFAULT (CONVERT(varchar(14), CAST(NEXT VALUE FOR customer_id_seq AS varbinary(7)), 2)),
    customer_name varchar(100) NOT NULL,
    CONSTRAINT pk_customers PRIMARY KEY(customer_id)
)

插入陈述:

INSERT INTO customers(customer_name) VALUES ('ACME');
INSERT INTO customers(customer_name) VALUES ('Marvel');

GO

INSERT INTO customers(customer_id, customer_name)
VALUES (CONVERT(varchar(14), CAST(NEXT VALUE FOR customer_id_seq AS varbinary(7)), 2), 'Fox');

INSERT INTO customers(customer_id, customer_name)
VALUES (CONVERT(varchar(14), CAST(NEXT VALUE FOR customer_id_seq AS varbinary(7)), 2), 'Columbia');

答案 1 :(得分:0)

您可以使用AFTER INSERT触发器查看CustIDinserted的值,然后使用该值的某些转换填充CustomerID(如十六进制或任何其他公式)我很关注。

答案 2 :(得分:0)

不确定你在这里要做什么。你的帖子说"自动增加",不知道这意味着什么。但您的示例输出看起来像随机数据。所以我把它们放在一起演示如何用一些标准生成一个14个字符的随机字符串。我在这里使用计数表使这更容易一些。你可以在这里阅读更多相关信息。 http://www.sqlservercentral.com/articles/T-SQL/62867/

我在我的系统上保留了一个计数表。代码看起来像这样。

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally

这里另一个具有挑战性的部分是我们想要在使用函数时获取随机值。这是一个难题,因为获得随机值的最佳方法是使用NEWID()的顺序。但是你不能在一个函数中做到这一点。但一切都不会丢失。我们可以创建一个视图,向我们返回一个NEWID()并将其用作订单谓词。这是该观点。

CREATE VIEW dbo.RandomID
AS
SELECT NewId() AS RandomID

现在我们只需要我们的功能。这不是很漂亮,但要求也有点不同寻常。我们需要获得14个随机字符,我们必须确保Customer表中不存在该值。

create function CreateAbsurdKey()
returns varchar(14) as
begin

    declare @Key varchar(14) = '';

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    select top 1 @Key = @Key + CHAR(t.N)
    from cteTally t
    where 
    (t.N >= 48 AND t.N <= 57)
        OR
    (t.N >= 65 AND t.N <= 90)
    order by (select RandomID from RandomID)

    --This will use recursion if the generated value already exists
    while exists(select * from Customer where customerID = @key)
    begin
        select @key = dbo.CreateAbsurdKey()
    end

    return @Key
end

最后但并非最不重要的是你可以如何使用它。

insert Customer
select dbo.CreateAbsurdKey()
    , 'Lange'
    , 'Sean'

您可以重复运行它,它将继续插入customerID的新值。

select * from Customer

答案 3 :(得分:0)

我的回答: 为了保证唯一性,必须确保它不存在于另一个寄存器中

CREATE TABLE Customer
(
CustID INT IDENTITY(1,1) PRIMARY KEY,
customerID VARCHAR(14) default CONVERT(VARCHAR(14), CRYPT_GEN_RANDOM(14), 2 ),
field1 VARCHAR(20)
)

INSERT INTO Customer (field1 ) VALUES ('Customer1')
INSERT INTO Customer (field1 ) VALUES ('Customer2')
INSERT INTO Customer (field1 ) VALUES ('Customer3')
INSERT INTO Customer (field1 ) VALUES ('Customer4')
INSERT INTO Customer (field1 ) VALUES ('Customer5')

SELECT * FROM Customer
GO
DROP TABLE Customer
GO

答案 4 :(得分:0)

CREATE TABLE dbo.Customer(
    CustID INT IDENTITY(1,1) PRIMARY KEY,
    customerID uniqueidentifier constraint [df_customer_customerID] DEFAULT(NEWID()),  --NEWID should be as unique as it gets????
    LastName varchar(300),
    FirstName varchar(300)NOT NULL
)


declare @i int = 1
while @i < 100000
begin
    insert dbo.Customer(LastName,FirstName)
    select 'Last_' + convert(varchar(10),@i), 'First_' + convert(varchar(10),@i)
    set @i = @i + 1
end

select customerID, count(1) from dbo.Customer group by customerID having count(1) > 1
select count(1) from dbo.Customer