生成唯一标识符作为基于集合的查询

Generating unique identifiers as a set based query

我正在将一堆代码从完全基于游标转移到基于集合并生成它一直在努力。我们为插入数据库的每个公司创建一个 6 个字符的简码(唯一的)并且我(想要) 在游标之外实现此目的。

目前我所处位置的示例:

CREATE TABLE #customers (name VARCHAR(50), shortname VARCHAR(10))
INSERT INTO #customers VALUES
('Michael Smith', 'Michae')
,('Michael Douglas', 'Mich_1')
,('Michael Yang', 'Mich_2')

CREATE TABLE #newcustomers (name VARCHAR(50), shortname VARCHAR(10) NULL)
INSERT INTO #newcustomers (name) VALUES
('Michael Black')
,('Michael White')

SELECT * FROM #customers
SELECT * FROM #newcustomers

DECLARE @shortname VARCHAR(10)
DECLARE @iteration INT = 0

WHILE EXISTS(SELECT shortname FROM #customers WHERE shortname = @shortname)
BEGIN
    SELECT @shortname = LEFT(name, 6) FROM #newcustomers

    UPDATE #newcustomers SET shortname = @shortname

    SET @shortname = LEFT(@shortname, 4) + '_' + @iteration

    SET @iteration = @iteration + 1
END

希望该示例足以确定我要到达的位置,任何建议或示例都会非常有帮助。我的示例不起作用。

一种选择是使用 computed column

table 按照这些思路进行设计是可行的:

- Sample table.
DECLARE @Sample TABLE
    (
        Id          INT IDENTITY(1, 1),
        FullName    VARCHAR(255),
        ShortName   AS LEFT(FullName, 4) + '_' + CAST(Id AS VARCHAR(255))
    )
;

-- Add set containing two companies.
INSERT INTO @Sample
    (
        FullName
    )
VALUES
    ('ABC LTD'),
    ('XYZ PLC')
;

Returns

Id  FullName    ShortName
1   ABC LTD     ABC _1
2   XYZ PLC     XYZ _1

IdShortName 列将由 SQL 服务器管理。您只需要添加 FullName.

编辑

使用 table 变量重写示例,使其更容易一起玩。

试试这个

您的 table 作为 模型

CREATE TABLE #customers (ID INT IDENTITY, name VARCHAR(50), shortname VARCHAR(10))
INSERT INTO #customers VALUES
('Michael Smith', 'Michae')
,('Michael Douglas', 'Mich_1')
,('Michael Yang', 'Mich_3')
,('Testman', 'Testma')
,('Testman1', 'Test_1');

CREATE TABLE #newcustomers (ID INT IDENTITY,name VARCHAR(50), shortname VARCHAR(10) NULL)
INSERT INTO #newcustomers (name) VALUES
('Michael Black')
,('Michael White')
,('Testman2')
,('Someone new');

--此 CTE 将合并所有现有名称

WITH AllNames AS
(
    SELECT '1_old' AS datasource,ID,name,shortname FROM #customers
    UNION ALL SELECT '2_new',ID,name,shortname FROM #newcustomers
)

--本CTE将使用组合列表并计算出正确的"index"

,ShortNames AS
(
    SELECT c.*
          ,A.First6
          ,ROW_NUMBER() OVER(PARTITION BY A.First6 ORDER BY datasource,ID) AS NrTotal
          ,ROW_NUMBER() OVER(PARTITION BY datasource,A.First6 ORDER BY datasource,ID) AS Nr
          ,CASE WHEN ISNUMERIC(SUBSTRING(shortname+'      ',6,10))=1 
                THEN CAST(SUBSTRING(shortname+'      ',6,10) AS INT) ELSE 0 END AS ExistIndex
    FROM AllNames AS c
    CROSS APPLY(SELECT LEFT(name + '      ',6)) AS A(First6)
)

--NrTotal=1 的所有新的按原样获取 6 个字母,所有其他获取索引

SELECT *
      ,CASE WHEN datasource='1_old' THEN shortname ELSE
        CASE WHEN datasource='2_new' AND NrTotal=1 THEN First6 
             ELSE LEFT(First6,4) + '_' + CAST(Nr + (SELECT ISNULL(MAX(x.ExistIndex),1)
                                                      FROM ShortNames AS x 
                                                      WHERE x.First6=ShortNames.First6) AS VARCHAR(5)) 
        END
       END
FROM ShortNames

GO
DROP TABLE #customers;
DROP TABLE #newcustomers;

结果

+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| datasource | ID | name            | shortname | First6 | NrTotal | Nr | ExistIndex | (Kein Spaltenname) |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 1_old      | 1  | Michael Smith   | Michae    | Michae | 1       | 1  | 0          | Michae             |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 1_old      | 2  | Michael Douglas | Mich_1    | Michae | 2       | 2  | 1          | Mich_1             |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 1_old      | 3  | Michael Yang    | Mich_3    | Michae | 3       | 3  | 3          | Mich_3             |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 1_old      | 4  | Testman         | Testma    | Testma | 1       | 1  | 0          | Testma             |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 1_old      | 5  | Testman1        | Test_1    | Testma | 2       | 2  | 1          | Test_1             |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 2_new      | 1  | Michael Black   | NULL      | Michae | 4       | 1  | 0          | Mich_4             |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 2_new      | 2  | Michael White   | NULL      | Michae | 5       | 2  | 0          | Mich_5             |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 2_new      | 4  | Someone new     | NULL      | Someon | 1       | 1  | 0          | Someon             |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+
| 2_new      | 3  | Testman2        | NULL      | Testma | 3       | 1  | 0          | Test_2             |
+------------+----+-----------------+-----------+--------+---------+----+------------+--------------------+