【问题标题】:Return ID if record exist, else Insert and return ID如果记录存在则返回 ID,否则插入并返回 ID
【发布时间】:2015-08-19 12:32:13
【问题描述】:

我有下面的 C# 代码来检查记录是否不存在,插入并返回 id。但我也需要如果记录存在,它会返回值。为了发生这种情况,我应该对 C# 和 SQL 部分进行哪些更改?数据库是 SQL 服务器。我还需要为此使用 ExecuteScalar() 吗?

con.Open();

// Insert ClinRefFileTypeMaster
string command1 = string.Format(
    "if NOT exists (select * from [ClinRefFileTypeMaster] where [ClinRefTypeName] = '{0}') Insert into [ClinRefFileTypeMaster] ([ClinRefTypeName]) output INSERTED.[ClinRefTypeID] VALUES('{0}')",
      dataToParse[i][0]
      );
SqlCommand ClinRefFileTypeMaster = new SqlCommand(command1, con);

// check if there is an value 
object checkValue = ClinRefFileTypeMaster.ExecuteScalar(); 

if (checkValue != null)
    ClinRefFileTypeId = (int)checkValue;

【问题讨论】:

  • 可能你需要 MERGE 语句
  • 也许拆分语句。仅插入 if 块。选择外面。 SQL 在缓存方面非常好,如果您刚刚插入一些选择它可能会非常快。另外查询很难阅读,请以@开头。
  • 这个样子Little Bobby Tables 不知道。
  • 类似的解决方案是here
  • 或者使用 DECLARE recordId int;然后 SELECT recordId = idColumn FROM tbl...

标签: c# sql-server visual-studio-2013


【解决方案1】:

为你做所有事情的存储过程看起来像.....

CREATE PROCEDURE usp_Get_ClinRefTypeID
  @ClinRefTypeName  VARCHAR(100),
  @ClinRefTypeID    INT OUTPUT
AS
BEGIN
  SET NOCOUNT ON;

    DECLARE @NewID TABLE(ClinRefTypeID INT);

  SELECT @ClinRefTypeID = [ClinRefTypeID]
  FROM [ClinRefFileTypeMaster] 
  where [ClinRefTypeName] = @ClinRefTypeName;

  IF (@ClinRefTypeID IS NULL)
    BEGIN
        INSERT INTO [ClinRefFileTypeMaster] ([ClinRefTypeName]) 
        OUTPUT inserted.[ClinRefTypeID]  INTO @NewID(ClinRefTypeID)
        VALUES(@ClinRefTypeName)

        SELECT @ClinRefTypeID = [ClinRefTypeID] FROM @NewID
    END

END

你的 C# 代码看起来像.....

con.Open();

// Insert ClinRefFileTypeMaster
    SqlCommand cmd = new SqlCommand("usp_Get_ClinRefTypeID", con);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@ClinRefTypeID", SqlDbType.Int).Direction = ParameterDirection.Output;
    cmd.Parameters.Add(new SqlParameter("@ClinRefTypeName", dataToParse));

// get the value back from the output parameter 
    cmd.ExecuteNonQuery();
    int ClinRefTypeName = Convert.ToInt32(cmd.Parameters["@ClinRefTypeID"].Value);

【讨论】:

  • 是的,我强烈推荐这种方式!更安全,更容易维护。
【解决方案2】:

有很多方法可以实现这一点。 1) 你可以在 inline Sql 中完成所有操作 2) 你可以在存储过程中完成所有操作。 3)您可以在代码中完成所有操作,但拆分代码,因为坦率地说,这段代码做得太多了。一般来说,我会避免使用相同的方法插入/查询。

也尝试使用 SqlParameters 而不是将查询构建为字符串连接。

我会提出这样的建议,使代码更具可读性

    public int InsertAndRetrieveClientRefId(string clientRefTypeName)
    {
        int id = GetIdIfRecordExists(clientRefTypeName);

        if (id == 0)
        { 
            // insert logic here

            id = GetIdIfRecordExists(clientRefTypeName);
        }

        return id;
    }

    public int GetIdIfRecordExists(string clientRefTypeName)
    {
        int id = 0;

        string command = "select id from ClinRefFileTypeMaster where ClinRefTypeName = @ClinRefTypeName";
        SqlParameter nameParameter = new SqlParameter("@ClinRefTypeName", System.Data.SqlDbType.NVarChar, 10) { Value = clientRefTypeName };

        using (SqlConnection connection = new SqlConnection("ConnectionString"))
        {
            using (SqlCommand cmd = new SqlCommand(command))
            {
                cmd.Parameters.Add(newParameter);
                connection.Open();
                cmd.Connection = connection;
                int.TryParse(cmd.ExecuteScalar().ToString(), out id);
            }
        }

        return id;
    }

【讨论】:

  • 谢谢,这对我有用,因为我不能选择使用存储过程。我认为您只是忘记将 nameParameter 添加到命令中!我做到了,效果很好。
  • 很高兴它成功了。我已经更新了将参数添加到命令的答案。
【解决方案3】:

在数据库中执行所有这些操作,即在存储过程中

if not exists (select 1 from  [ClinRefFileTypeMaster] where [ClinRefTypeName] =@name)
begin
Insert into [ClinRefFileTypeMaster] ([ClinRefTypeName]) values (@name) 
end
else
begin
select (as desired) from ClinRefFileTypeMaster where where [ClinRefTypeName] =@name
end

这将插入新记录或选择已插入的信息

【讨论】:

    【解决方案4】:

    您还需要在 SQL 语句中添加一个 IF EXISTS 子句,检查相同的条件,并提供返回值的逻辑。

    如果您需要它从数据库中返回值,似乎使用 ExecuteReader 会更好。

    2¢ 我个人会将逻辑拆分为两个查询,并在 c# 中运行 If 语句,检查值是否在数据库中,然后更新数据库,否则会从数据库中返回一个值

    conn.open()
    int CheckDb;
    String Command1 = "select * from [ClinRefFileTypeMaster] where [ClinRefTypeName] = @ClinRefFileTypeId";
    using (SqlCommand ClinRefFileTypeMaster = new SqlCommand(command1, con);
        {
             cmd.Parameters.AddWithValue("@ClinRefFileTypeId", {0});
             CheckDb = (int)ClinRefFileTypeMaster.ExecuteScalar();
         }
    If (CheckDb != 0)
        //Logic for returning the value from the database
    Else
        //Here you can request user check data or insert the value into the database.
    

    【讨论】:

      【解决方案5】:

      如果你想执行 Instert 操作,我认为你最好调用一个存储过程并在过程中编写你的查询。会更安全。

      SqlCommand command = new SqlCommand("procedureName",con);
      command.CommandType = CommandType.StoredProcedure;
      command.Parameters.AddWithValue(“@value1”, txtValue1.Text);
      command.Parameters.AddWithValue(“@value2”, Value2);
      int value = command.ExecuteScalar();
      

      IF EXISTS (SELECT 1 FROM Table WHERE FieldValue='') 
      BEGIN
      SELECT TableID FROM Table WHERE FieldValue=''
      END
      ELSE
      BEGIN
      INSERT INTO TABLE(FieldValue) VALUES('')
      SELECT SCOPE_IDENTITY() AS TableID
      END
      

      如果要传递查询字符串,可以调用选择查询,如果返回null,则执行插入操作并使用scope_Identity() 获取ID

      INSERT INTO YourTable(val1, val2, val3 ...) 
      VALUES(@val1, @val2, @val3...);
      SELECT SCOPE_IDENTITY();
      

      【讨论】:

        猜你喜欢
        • 2013-12-27
        • 2014-04-28
        • 1970-01-01
        • 2019-09-06
        • 2013-08-14
        • 1970-01-01
        • 2013-06-18
        • 1970-01-01
        • 2016-01-18
        相关资源
        最近更新 更多