【问题标题】:Update if the name exists else insert - in SQL Server如果名称存在则更新否则插入 - 在 SQL Server 中
【发布时间】:2016-08-31 12:31:16
【问题描述】:

如果给定的文件名已经在我的数据库中,我想在我的表中更新,否则我想插入一个新行。我尝试了这段代码,但EXISTS 显示的错误请给我正确的方法,因为我在 SQL 中更新鲜

public void SaveData(string filename, string jsonobject)
{
    SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=;Integrated Security=True");
    SqlCommand cmd;
    SqlCommand cmda;

    if EXISTS("SELECT * FROM T_Pages WHERE pagename = '" + filename + "") {
        cmda = new SqlCommand("UPDATE T_Pages SET pagename='" + filename + "',pageinfo='" + jsonobject + "' WHERE pagename='" + filename + "'", con);
        cmda.ExecuteNonQuery();
    }
    else {
        cmd = new SqlCommand("insert into T_Pages (pagename,pageinfo) values('" + filename + "','" + jsonobject + "')", con);
        cmd.ExecuteNonQuery();
    }

    con.Close();
}

【问题讨论】:

  • if EXISTS 是什么?你在 C# 代码中。你不能在 C# 代码中编写 SQL 语法
  • 你定义/实现了 EXIST 函数吗?你需要。
  • MERGE 就是为了这个目的
  • MERGE 在这里是一个糟糕的选择,在一个批次中使用 IF EXISTS/INSERT/UPDATE。
  • SQL Injection alert - 您应该将您的 SQL 语句连接在一起 - 使用 参数化查询 来避免 SQL 注入

标签: c# sql sql-server


【解决方案1】:

你应该

  • 在您的查询中使用 参数 - 总是! - 没有例外
  • 创建一个查询来处理服务器上的IF EXISTS() 部分
  • 使用公认的 ADO.NET 最佳实践,将内容放入 using() {....} 块等中。

试试这个代码:

public void SaveData(string filename, string jsonobject)
{
    // define connection string and query
    string connectionString = "Data Source=.;Initial Catalog=;Integrated Security=True";
    string query = @"IF EXISTS(SELECT * FROM dbo.T_Pages WHERE pagename = @pagename)
                        UPDATE dbo.T_Pages 
                        SET pageinfo = @PageInfo
                        WHERE pagename = @pagename
                    ELSE
                        INSERT INTO dbo.T_Pages(PageName, PageInfo) VALUES(@PageName, @PageInfo);";

    // create connection and command in "using" blocks
    using (SqlConnection conn = new SqlConnection(connectionString))
    using (SqlCommand cmd = new SqlCommand(query, conn))
    {
        // define the parameters - not sure just how large those 
        // string lengths need to be - use whatever is defined in the
        // database table here!
        cmd.Parameters.Add("@PageName", SqlDbType.VarChar, 100).Value = filename;
        cmd.Parameters.Add("@PageInfo", SqlDbType.VarChar, 200).Value = jsonobject;

        // open connection, execute query, close connection
        conn.Open();
        int rowsAffected = cmd.ExecuteNonQuery();
        conn.Close();
    }
}

【讨论】:

    【解决方案2】:

    使用一个MERGE 语句怎么样?
    当然用参数来避免SQL injection的风险。

    public void SaveData(string filename, string jsonobject)
    {
      SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=;Integrated Security=True");
    
      SqlCommand cmd;
    
      cmd = new SqlCommand(@"
        MERGE T_Pages AS target  
        USING (SELECT @PageName as pagename, @PageInfo as pageinfo) AS source 
        ON (target.pagename = source.pagename)  
        WHEN MATCHED THEN   
            UPDATE SET pageinfo = source.pageinfo  
        WHEN NOT MATCHED THEN  
        INSERT (pagename, pageinfo)  
        VALUES (source.pagename, source.pageinfo)", con);
    
       cmd.Parameters.Add(new SqlParameter("@PageName", filename));
       cmd.Parameters.Add(new SqlParameter("@PageInfo", jsonobject));
    
       con.Open();
       cmd.ExecuteNonQuery();
       con.Close();
     }
    

    【讨论】:

    • 是的,在这种情况下,MERGE 应该是完美的。取决于 SQL Server 版本。我相信它只是在 SQL 2008 中引入的......
    • 确实,MERGE 是在 2008 版本中引入的。基于 SQL:2003 标准。由于问题没有指定数据库版本,因此不能假设它必须在 SQL Server 2005 或更早版本上运行:)
    【解决方案3】:

    在数据库上创建存储过程

    CREATE PROCEDURE T_Pages_Write  (@pagename nvarchar(256) ,@pageinfo nvarchar(max)) 
    AS
    IF EXISTS (SELECT pagename from T_Pages WHERE pagename = @pagename)
    UPDATE T_Pages SET pageinfo = @pageinfo WHERE pagename = @pagename
    ELSE 
    INSERT T_Pages (pagename, Pageinfo) VALUES (@pagename, @Pageinfo)
    

    然后从您的代码中调用它。你真的应该用参数化的命令来做到这一点(会有很多其他问题建议你最好的方法)。如果您愿意冒 SQL 注入攻击的风险,并且不介意在数据中有单引号字符时它会失败,那么您可以像这样快速而肮脏的方式来做到这一点

    cmd = new SqlCommand("EXEC T_PagesWrite @pagename = '" + filename + "', @pageinfo ='" + jsonobject + "'", con);
    

    【讨论】:

      【解决方案4】:
      public void SaveData(string filename, string jsonobject)
          {
              SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=;Integrated Security=True");
              SqlCommand cmd;
              SqlCommand cmda;
      
              SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM T_Pages WHERE pagename = '" + filename + "", con);
              DataSet ds = new DataSet();
              da.Fill(ds);
      
      
      
              if (ds.Tables[0].Rows.Count > 0)
              {
      
                  cmda = new SqlCommand("UPDATE T_Pages SET pagename='" + filename + "',pageinfo='" + jsonobject + "' WHERE pagename='" + filename + "'", con);
                  cmda.ExecuteNonQuery();
              }
              else
              {
                  cmd = new SqlCommand("insert into T_Pages (pagename,pageinfo) values('" + filename + "','" + jsonobject + "')", con);
                  cmd.ExecuteNonQuery();
              }
      
      
              con.Close();
      
      
      
          }
      

      【讨论】:

        【解决方案5】:

        您可以通过一个查询来完成此操作

        您要在哪里标记 int 类型的标志变量(您也可以将其设为 tinyint 类型,由您决定),如果计数为 0,则表示没有行,否则您更新查询

        SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=;Integrated Security=True");
        SqlCommand cmd;
        cmda = new SqlCommand("declare @flag int ;set @flag = 0;select @flag = COUNT(*) FROM T_Pages WHERE pagename = '" + filename + "';IF @flag = 1 UPDATE T_Pages SET pagename='" + filename + "',pageinfo='" + jsonobject + "' WHERE pagename='" + filename + "';ELSE insert into T_Pages (pagename,pageinfo) values('" + filename + "','" + jsonobject + "');", con);
        cmda.ExecuteNonQuery();
        con.Close();
        

        【讨论】:

        • 为什么有人反对这个答案..?根据问题模式(如果不考虑 sql 注入 ...somthing ....)此代码正在运行。
        • @mr.cool ,你是对的,但我们能做些什么呢?这是他们认为的一些成员,他们是对的,因为我们看到提出问题的人从他的问题中没有 sql 注入的背景,但仍然是第二次 StackOverflow 让我心碎。 :(
        • 但我投了赞成票,因为作为一个新人,这段代码更容易理解
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-10-23
        • 2015-03-02
        • 2015-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-06
        相关资源
        最近更新 更多