Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在SQL Server自动递增键列中包含其他字符和符号_Sql Server_Primary Key - Fatal编程技术网

Sql server 在SQL Server自动递增键列中包含其他字符和符号

Sql server 在SQL Server自动递增键列中包含其他字符和符号,sql-server,primary-key,Sql Server,Primary Key,我开始做一个项目。除了基本信息,我没有很多经验。我只是想问一下,我可以在主键列中使用符号吗,如2015/1234等。这些是文件号,必须是唯一的,所以我决定将它们设为主键,但我不确定我是否可以使用符号,如果可以,我可以使用自动递增吗 2015/1234, 2015/1235 ... etc. 其中2015是一个年份数字。每年第二个序列号必须重置为1 编辑:如果可以完成所有操作,我应该使用哪种数据类型?自动递增(identity在T-SQL中)只能用于整数。它还限制了列插入的方式。解决您的需求的一

我开始做一个项目。除了基本信息,我没有很多经验。我只是想问一下,我可以在主键列中使用符号吗,如
2015/1234
等。这些是文件号,必须是唯一的,所以我决定将它们设为主键,但我不确定我是否可以使用符号,如果可以,我可以使用自动递增吗

2015/1234, 2015/1235 ... etc.
其中2015是一个年份数字。每年第二个序列号必须重置为1

编辑:如果可以完成所有操作,我应该使用哪种数据类型?

自动递增(
identity
在T-SQL中)只能用于整数。它还限制了列插入的方式。解决您的需求的一种方法可能是将数字范围指定给特定年份(20142015等),然后在查询中将这些数字转换回文件名,例如:2014年为1-1000000,2015年为1000001-2000000,等等。在select语句中,可以使用

Select cast(floor(id/1000000)+2014 as char(4))+'/'+cast(id % 1000000 as varchar(6)) mykey ... from table
但一般来说,我认为最好使用单独的编号表,如

mumtbl:
----------
year    mxidx_used
---------------------
2014       234
2015      1678

并将其用作要生成的新键的查找(之后不要忘记更新其中的最大值)。

您可以通过将
FileNumber
的类型更改为
VARCHAR(x)
,但假设您需要
序列部分(即
1234
),将您的文件号设置为主键您将无法利用标识列(Sql Server的自动递增值),因为这将在每年之后继续增加

您可以保留一个
VARCHAR FileNumber
PK并自己管理文件号生成,但我建议您不要这样做-这对并发性有害,因为两个写入程序同时插入需要争夺序列号的“下一个”值-这通常会导致可怕的,已锁定
SELECT MAX..。
insert前的查询或外部“next value”表(尽管在Sql Server 2012+中)将为您管理此操作

相反,我建议只使用代理整数标识(例如,
ID INT-identity(1,1)
作为PK-Sql Server将处理并发性,其他FK引用您的表的范围更窄

然后,添加编码的natural/composite
FileNumber
字段,并包含一个额外的唯一键约束列,或者更好,只需将
FileNumber
作为两个单独的列分解到其组成部分,即
Year int
SequenceInYear int
。然后,您可以始终使用计算列重新生成完整的
FileNumber
字符串

实施

在绝对假设您无法将新文件插入旧年份的情况下,我将这样做:

CREATE SEQUENCE NextValueForCurrentYear
    START WITH 1
    INCREMENT BY 1 ;

CREATE TABLE MyTable
(
    -- Narrow surrogate key managed by Sql
    ID INT IDENTITY(1,1) NOT NULL CONSTRAINT PK_MyTable PRIMARY KEY,
    -- Provided during insert, or retrieved from some config table
    [Year] INT NOT NULL,
    -- Auto incrementing sequence
    SequenceNoInYear INT NOT NULL CONSTRAINT DF_SequenceNoInYear 
                DEFAULT NEXT value FOR NextValueForCurrentYear,
    -- Computed column - can be read, generated automatically
    FileNumber AS CAST([Year] AS VARCHAR(4)) + '/' + 
            CAST(SequenceNoInYear AS VARCHAR(10)),
    -- Other Columns here

    -- Ensure filenumber is unique
    CONSTRAINT UQ_MyTable UNIQUE([Year], SequenceNoInYear)
);
您所需要做的就是提供年份号,剩下的将被生成,即

INSERT INTO MyTable(Year) VALUES (2015);
如果您需要从1开始每年的序列号,那么您将需要每年


[Year],SequenceNoInYear上的唯一键约束将防止在序列号重置后插入旧年份。

最好的解决方案是使用

  • 一个
    ID INT-IDENTITY(1,1)
    列,用于让SQL Server处理数值的自动增量
  • 一个计算的、持久的列,用于将该数值转换为所需的值
所以试试这个:

CREATE TABLE dbo.YourTable
  (ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
   SomeDateColumn DATE,
   YourCompoundID AS RIGHT('00000' + CAST(ID AS VARCHAR(5)), 5) + '/' + CAST(YEAR(SomeDateColumn) AS VARCHAR(4)) PERSISTED,
   .... your other columns here....
  )
现在,每次在未指定
ID
CompanyID
值的情况下将行插入
tblCompany

INSERT INTO dbo.YourTable(SomeDateColumn, Col1, Col2, ..., ColN)
VALUES ('20150725', Val1, Val2, ....., ValN)

然后,SQL Server将自动且安全地增加您的
ID
值,
YourCompoundID
将包含
00001/2015
00002/2015
,……等值-自动、安全、可靠。

您必须在案例和公式中创建一个主键集初始值1233根据您的要求生成您的文件ID只需在数据库中运行我的查询,并尝试手动在表中插入名称,您就会看到结果,我希望这将对您有所帮助

/****** Object:  Table [dbo].[tblStringPrimaryKey]    Script Date: 7/25/2015 3:32:42 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[tblStringPrimaryKey](
    [Id] [int] IDENTITY(1233,1) NOT NULL,
    [FileId]  AS ((CONVERT([nvarchar](10),datepart(year,getdate()))+'/')+CONVERT([nvarchar](22),[Id])),
    [Name] [nvarchar](50) NULL,
 CONSTRAINT [PK_tblStringPrimaryKey] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
 CONSTRAINT [IX_tblStringPrimaryKey] UNIQUE NONCLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

是2015年我必须作为前缀,还是它将随着2016年的变化而变化?是的,它将随着2016年、2017年的变化而变化…看我的答案,只是在你的数据库中作为测试表运行,你得到了结果你的序列号需要在每一年开始时重置回1吗?是的,它必须重置为1谢谢你的答复我了解大部分内容,但我不知道nt询问是否从每个1开始year@ulmotl:在这种情况下,您需要一个从SQL Server 2012开始提供的
序列
;您可以在需要时重置序列,例如@StuartLC提到的每新年1月1日重置一次,我想首先感谢您的回复,在SQL fiddle中,它可以正常工作,但我想询问文件编号ber,它不是表上的id号,我想它不会以这种方式是唯一的,对吗?我的意思是,如果它能工作,它会自动增加吗?谢谢:)?但是我不明白你提到的过去的岁月。如果你这么说的话,我会为存档创建另一个表。虽然Filenumber是唯一的,但它不是主键IMO的好选择。我的回答显示了如何使用序列和计算列安全地派生唯一的文件号,尽管你每年都需要重置序列。存储年份和序列时,无需存档数据。旧年份的意思是,如果我们现在是2016年,序列已经重置,因此如果您需要插入一条被遗忘的2015年记录,您需要手动确定唯一的序列号,而不是使用序列默认值。