【问题标题】:Create stored procedure to add with auto increment as its primary field?创建存储过程以添加自动增量作为其主要字段?
【发布时间】:2012-05-23 18:26:38
【问题描述】:

我正在尝试通过 C# 将数据插入到我的 Sql-Server 数据库中。我正在调用一个存储过程,然后希望它添加。我不确定要进行哪些更改,但最终我希望它在存储过程中完成。

我现在的存储过程:

CREATE PROCEDURE [dbo].[InsertTagProcdure]
       @TagID int, 
       @Value nvarchar(200), 
       @TagCount nvarchar(200) 
AS
IF NOT EXISTS (SELECT NULL FROM Tag
                WHERE @TagID = @TagID)
BEGIN
    INSERT INTO 
        Tag 
        (TagID,Value,TagCount) 
        VALUES 
        (@TagID,@Value,@TagCount)
END

还有我的 C# 代码:

int TagID = int.Parse(txtTagID.Text); //This should fall away so auto increment.
            String Value = txtValue.Text;
            int TagCount = int.Parse(txtCount.Text); 

            using (var conn = new SqlConnection(Properties.Settings.Default.DBConnectionString))
            using (var cmd = conn.CreateCommand())
            {
                    conn.Open();
                    cmd.CommandText = "InsertTagProcdure";
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@TagID", TagID);
                    cmd.Parameters.AddWithValue("@Value", Value);
                    cmd.Parameters.AddWithValue("@TagCount", TagCount);
                    cmd.ExecuteNonQuery();
                }

我使用的表创建://不能改变这是老板给我的。

CREATE TABLE [dbo].[Tag](
    [TagID] [int] IDENTITY(1,1) NOT NULL,
    [Value] [varchar](200) NOT NULL,
    [TagCount] [varchar](200) NULL,
 CONSTRAINT [PK_Tag] PRIMARY KEY CLUSTERED 
(
    [TagID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

【问题讨论】:

  • 如果您在 SQL Server 中对主键启用自动递增,则无需传递 TagID,它会自动递增并为您分配。

标签: c# sql sql-server sql-server-2008 stored-procedures


【解决方案1】:

理想情况下,您只需通过更改表定义将 TagID 设为身份字段。如果你不能这样做,下一个最好的方法是:

CREATE PROCEDURE [dbo].[InsertTagProcdure]
       @Value nvarchar(200), 
       @TagCount nvarchar(200) 
AS
BEGIN
    BEGIN TRANSACTION
        DECLARE @TagID int;
        SELECT @TagID = coalesce((select max(TagID) + 1 from Tag), 1)
    COMMIT      
    INSERT INTO 
        Tag 
        (TagID,Value,TagCount) 
        VALUES 
        (@TagID,@Value,@TagCount)
END

事务确保您不会得到唯一的 TagID,并且合并处理表为空的特殊情况并给出初始值 1。

编辑:

根据您对原始问题的更改,该表已经有一个标识列,因此您的存储过程应该是:

CREATE PROCEDURE [dbo].[InsertTagProcdure]
       @Value nvarchar(200), 
       @TagCount nvarchar(200) 
AS
BEGIN
    INSERT INTO Tag (Value,TagCount) VALUES (@Value,@TagCount)
END

你的 C# 代码应该是

int TagID = int.Parse(txtTagID.Text); //这应该会自动增加。 字符串值 = txtValue.Text; int TagCount = int.Parse(txtCount.Text);

        using (var conn = new SqlConnection(Properties.Settings.Default.DBConnectionString))
        using (var cmd = conn.CreateCommand())
        {
                conn.Open();
                cmd.CommandText = "InsertTagProcdure";
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.AddWithValue("@Value", Value);
                cmd.Parameters.AddWithValue("@TagCount", TagCount);
                cmd.ExecuteNonQuery();
            }

【讨论】:

  • 我遇到了这个异常:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“标签”中插入标识列的显式值。
  • @Pomster - 我的回答是非此即彼的选择。如果您已将该列设置为标识列,那么您的问题就解决了 - 只需删除处理 TagID 的原始存储过程的位。我在这里给出的 SP 是为了防止您无权更改表架构。 HTH
  • 我不允许更改数据库设置上的任何东西,所以我厌倦了你的代码并得到了那个错误。我不知道你还告诉我做什么?
  • 你能用简单的话解释一下我应该怎么做吗?我有什么选择?我无法更改数据库的创建方式。
  • @Pomster 我刚刚做到了!从“编辑”一词中读取 - 您对存储过程进行了一些更改,并对您的 c# 代码进行了一些更改。复制并粘贴我放在那里的内容,你应该没问题。
【解决方案2】:

您想设置标记表,以便它使用标识属性。见这里:http://msdn.microsoft.com/en-us/library/aa933196(v=sql.80).aspx

然后你可以从过程中删除TagId,过程中的insert语句和c#代码。

然后变成这样:

CREATE PROCEDURE [dbo].[InsertTagProcdure]
       @Value nvarchar(200), 
       @TagCount nvarchar(200) 
AS
BEGIN
    INSERT INTO 
        Tag 
        (Value,TagCount) 
        VALUES 
        (@Value,@TagCount)
END

C#代码:

            String Value = txtValue.Text;
            int TagCount = int.Parse(txtCount.Text); 

            using (var conn = new SqlConnection(Properties.Settings.Default.DBConnectionString))
            using (var cmd = conn.CreateCommand())
            {
                    conn.Open();
                    cmd.CommandText = "InsertTagProcdure";
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@Value", Value);
                    cmd.Parameters.AddWithValue("@TagCount", TagCount);
                    cmd.ExecuteNonQuery();
                }

【讨论】:

    【解决方案3】:

    语句 WHERE @TagID = @TagID 将始终为真,因为您比较相同的值。 我认为您正在寻找这个(假设 TagID 是您的 AUTO-ID 字段);

    CREATE PROCEDURE [dbo].[InsertTagProcdure] 
           @TagID int,  
           @Value nvarchar(200),  
           @TagCount nvarchar(200)  
    AS 
    BEGIN
    IF NOT EXISTS (SELECT TagID FROM Tag WHERE TagID = @TagID) 
    BEGIN 
        INSERT INTO  
            Tag  
            (Value,TagCount)  
            VALUES  
            (@Value,@TagCount) 
      SET @TagID = @@IDENTITY
    END 
    ELSE
    BEGIN
      UPDATE Tag
        SET Value=@Value,
        TagCount=@TagCount
      WHERE TagID = @TagID
    END
    RETURN @TagID
    END
    

    【讨论】:

    • 无法创建存储过程错误:消息 102,级别 15,状态 1,过程 InsertTagTest,第 23 行“END”附近的语法不正确。
    • 我在存储过程的开头忘记了 BEGIN - 已调整,但我建议您阅读 Dave 的评论。
    【解决方案4】:

    您必须在 SQL Server 中的相应列上打开“身份规范”。进入表格设计模式,选择列,在底部属性屏幕中有一个名为“身份规范”的属性。

    在此之后,您可以在存储过程中省略 TagId。 Sql Server 会自动为新记录分配一个id。

    如果您想知道新插入的 id 是什么(我假设这是您的下一个问题),您可以在存储过程中使用函数 SCOPE_IDENTITY(),它返回新插入记录的 id。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-10
      • 1970-01-01
      • 2014-02-10
      • 2012-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-24
      相关资源
      最近更新 更多