【发布时间】:2013-12-20 22:15:50
【问题描述】:
我正在尝试在 SQL Server 2008 中创建一个过程,以获取任何表的新主键值(最大值 + 1)(表名将是输入参数)...我的代码如下:
CREATE PROCEDURE [dbo].[SysGetNewPrimaryKey]
(@TableName AS NVARCHAR(100)) AS
BEGIN
SET NOCOUNT ON;
DECLARE @PrimaryKey AS NVARCHAR(128)
DECLARE @PrimaryKeyLength AS INT
DECLARE @MaxValue AS NVARCHAR(10)
DECLARE @sql AS NVARCHAR(4000)
DECLARE @ParmDefinition AS NVARCHAR(500)
DECLARE @_PKInfo TABLE
(
DbName NVARCHAR(128)
,OwnerName NVARCHAR(128)
,TableName NVARCHAR(128)
,ColumnName NVARCHAR(128)
,KeySeq INT
,PkName NVARCHAR(128)
)
INSERT INTO @_PKInfo EXEC sp_Pkeys @TableName
SET @PrimaryKey = (SELECT ColumnName FROM @_PKInfo)
SET @PrimaryKeyLength = (SELECT COLUMNPROPERTY( OBJECT_ID(@TableName),@PrimaryKey,'PRECISION'))
select @primaryKey, @PrimaryKeyLength
SET @sql = 'SET @MaxValueOUT = (SELECT (ISNULL(MAX(@PrimaryKeyIN), 1) + 1) FROM ' + quotename(@TableName) + ')'
SET @ParmDefinition = '@PrimaryKeyIN NVARCHAR(128),
@MaxValueOUT NVARCHAR(10) OUTPUT'
EXEC sp_executesql
@sql,
@ParmDefinition,
@PrimaryKeyIN = @PrimaryKey,
@MaxValueOUT = @MaxValue OUTPUT
SELECT RIGHT(REPLICATE('0', @PrimaryKeyLength) + @MaxValue, @PrimaryKeyLength)
END
GO
当我尝试执行此过程时,会出现以下错误: 消息 245,第 16 级,状态 1,第 2 行 将 nvarchar 值“CityCode”转换为数据类型 int 时转换失败。
请告知是什么问题。示例表可以是:
城市标签
城市代码 nvarchar(10) CityDesc nvarchar(250)
编辑部分:(在查看以下 cmets 后)
如果我将创建此列 IDENTITY 然后尝试运行以下脚本来了解我的问题
CREATE TABLE [dbo].[TblCity](
[CityCode] [int] IDENTITY(1,1) NOT NULL ,
[CityDesc] [nvarchar](250) NOT NULL DEFAULT (''),
[CreationUser] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_TblCity] PRIMARY KEY CLUSTERED
([CityCode] 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
INSERT INTO TblCity (CityDesc, CreationUser) VALUES ('Jeddah', 'sa')
INSERT INTO TblCity (CityDesc, CreationUser) VALUES ('Riyadh', 'sa')
INSERT INTO TblCity (CityDesc, CreationUser) VALUES ('Dammam', 'sa')
SELECT * FROM TblCity
INSERT INTO TblCity (CityDesc, CreationUser) VALUES ('Taif', NULL) -- This statement raises ERROR
INSERT INTO TblCity (CityDesc, CreationUser) VALUES ('Taif', 'sa')
SELECT * FROM TblCity -- 4 is missing now
最好的问候
齐山
【问题讨论】:
-
可能的目的是什么?即使您在这里解决了语法问题,在实际运行插入之前获取“下一个”IDENTITY 值又有什么意义呢?因为除非您先插入然后检索您生成的值,否则无法保证“下一个”值在您插入时仍然可用。
-
+1 对于亚伦的怀疑……我也有同样的担忧。如果你这样做是因为它不是一个 IDENTITY,你应该让它成为一个身份,并让 SQL Server 担心并发性和一致性。如果它已经是一个标识值,并且您想知道下一个生成的标识值是什么而不是试图手动潜入(坏主意),请使用
DBCC CHECKIDENT(YourTable, NORESEED),它实际上处理了最最近的身份已被删除或回滚。 -
我的表中已经有一个标识列,必须用于其他目的......我正在考虑删除另一列以使该列成为 IDENTITY 但会有一个问题好像由于任何错误记录都不会插入,即使 SQL Server 会增加值,并且键中会有间隙,这在审计时可能是一个问题。如果出现任何错误,有没有办法将 IDENTITY 重置为以前的值?
-
previous value是什么意思? Alice 插入 1,Carol 插入 2,Bob 尝试 3,Ted 插入 4,Bob 进行回滚。现在你有 1、2 和 4。你想接下来做 3,然后是 5?您真正需要的是新版本的审核员。当他们看到 SQL Server 2012 在干净重启时可以跳过多少值时,他们会感到很舒服。
-
@HABO .. 举个例子... Alice 插入 1,Carol 插入 2,Bob 尝试 3,但是 SQL 在插入语句中引发了一些错误。 Bob 更正了该错误并再次插入。但它插入“4”而不是 3。如果表中有 4,我不想再做 3,但如果插入语句中有任何错误,它应该重置为 MAX 值。尝试在我的问题中运行脚本以进一步解释我的问题
标签: sql-server-2008