在sql中生成自定义序列

时间:2017-06-21 08:26:28

标签: sql sql-server

我想为每条记录生成自定义序列。

示例:如果用户下订单,则订单号应为 ORD-17-001

对于下一个订单,它应该像 ORD-17-002 ,依此类推。

'的 17 '是今年。所以在2018年的第一个订单应该是 ORD-18-001。

任何人都可以提出解决方案。我不是sql命令的专家。

4 个答案:

答案 0 :(得分:0)

是的,查看触发器。插入行时,可以使数据库自动执行代码。

CREATE TRIGGER trig_Update_order
ON [OrdersTable]
FOR INSERT
AS
Begin
    --- write your code to generate the order number here
    --- you can select stuff from the newly inserted row by using "Inserted"
    --- like this
    --- select name from Inserted --- this will return the name column of the new row
End

有关插入触发器的更多文档,请访问: https://docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql

答案 1 :(得分:0)

这是使用生成的订单号的答案,这是使用订单年份和表格的标识列的组合生成的(为了保证订单保持一致,这假设没有删除)。如果删除可能发生,那么你需要按照安东尼霍恩的评论采用触发方式。

  

设置

CREATE TABLE OrderDetails
(
    ID INT Identity,
    CustomerID INT,
    OrderDate Date,
    CreatedDate DATETIME DEFAULT getdate(),
    OrderValue Decimal(18,2)
)
GO
CREATE VIEW vwOrder
As
    SELECT 
       CustomerId, OrderDate, CreatedDate, OrderValue,
       'ORD-' + 
       RIGHT(CAST(YEAR(OrderDate) AS CHAR(4)),2) + '-' + 
       RIGHT('00' + 
       CAST(ROW_NUMBER() OVER (PARTITION BY YEAR(OrderDate) ORDER BY ID) AS VARCHAR(3)),3) AS OrderNumber
    FROM OrderDetails
GO
INSERT INTO OrderDetails (CustomerId, OrderDate, OrderValue)
VALUES
    (1, '2017-6-12', 20.45),
    (1, '2017-6-12', 30.25),
    (1, '2017-6-13', 10.23),
    (2, '2017-7-12', 5.23),
    (2, '2018-6-01', 55.0),
    (1, '2016-12-01', 22)
GO
  

查询

SELECT *
FROM VwOrder
  

结果

CustomerId OrderDate  CreatedDate             OrderValue OrderNumber
1          2016-12-01 2017-06-21 10:19:44.613 22.00      ORD-16-001
1          2017-06-12 2017-06-21 10:19:44.613 20.45      ORD-17-001
1          2017-06-12 2017-06-21 10:19:44.613 30.25      ORD-17-002
1          2017-06-13 2017-06-21 10:19:44.613 10.23      ORD-17-003
2          2017-07-12 2017-06-21 10:19:44.613  5.23      ORD-17-004
2          2018-06-01 2017-06-21 10:19:44.613 55.00      ORD-18-001

答案 2 :(得分:0)

  1. 在每个插入
  2. 上创建一个触发器
  3. 然后使用substring(cast(year(GETDATE()) as varchar),3,2)获取日期部分,可以使用多种方法,如果能找到更好的内容,请尝试
  4. 现在您需要获取最后一个数字的值,并查看年份是否与当前数字相同。 如果它相同然后增加它, 如果以前记录的年份与当前记录不同,则将新数字初始化为零。您可能希望阅读条件语句和SQL中的变量。

答案 3 :(得分:0)

我会使用以下解决方案:

https?:\/\/?[-a-zA-Z0-9@:%._\+~#=\[\]]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\ +.~#?&//=]*)

注意:生成新值的源代码可以封装在具有2个INPUT参数和1个OUTPUT参数的存储过程中。

注意#2:每年仅使用三位数(000)作为订单号(!)是一个糟糕的选择。这意味着每年最多999个订单。 相反,如果这些代码的订单号至少应为3位数,那么我会使用(SQL2012 +)FORMAT函数:

/*
CREATE TABLE dbo.CustomSequence (
    Name VARCHAR(50) NOT NULL
        CONSTRAINT PK_CustomSequence_Name PRIMARY KEY (Name),
    Prefix      VARCHAR(10) NOT NULL,
    LastValue   VARCHAR(50) NULL -- All generated values will have following pattern: Pattern-YY-SeqvNumber
);
GO
-- Config OrderSequence
INSERT  dbo.CustomSequence (Name, Prefix, LastValue) 
VALUES  ('OrderSequence', 'ORD', NULL)
GO
-- Config InvoiceSequence
INSERT  dbo.CustomSequence (Name, Prefix, LastValue) 
VALUES  ('InvoiceSequence', 'INV', NULL)
GO
*/

-- IN Parameters
DECLARE @CustomSequenceName VARCHAR(50) = 'OrderSequence'
DECLARE @Year               INT = 2019
-- End of IN Parameters
-- OUT Parameters
DECLARE @GeneratedValue     VARCHAR(50)
-- End of OUT Parameters

UPDATE  s
SET     @GeneratedValue = LastValue = CASE WHEN s.LastValue IS NULL
            THEN s.Prefix + '-' + RIGHT(@Year, 2) + '-001' -- There is no current value
            ELSE CASE WHEN PARSENAME(REPLACE(s.LastValue, '-', '.'), 2) = RIGHT(@Year, 2) -- PARSENAME('A.B.C', 1) returns 'C', PARSENAME('A.B.C', 2) returns 'B'
                THEN s.Prefix + '-' + RIGHT(@Year, 2) + '-' + RIGHT('000000' + LTRIM(CONVERT(SMALLINT, PARSENAME(REPLACE(s.LastValue, '-', '.'), 1)) + 1), 3)
                ELSE s.Prefix + '-' + RIGHT(@Year, 2) + '-001' -- New year, so we have to restart numbering with 1
            END
        END
FROM    dbo.CustomSequence s
WHERE   s.Name = @CustomSequenceName;

SELECT  @GeneratedValue
SELECT  *
FROM    dbo.CustomSequence s;

这意味着在THEN s.Prefix + '-' + RIGHT(@Year, 2) + '-' + FORMAT((CONVERT(SMALLINT, PARSENAME(REPLACE(s.LastValue, '-', '.'), 1)) + 1), '000') 下次生成的值为ORD-17-999而不是ORD-19-1000(截断)之后。

相关问题