如果名称存在,则更新,否则插入 - 在SQL Server中。

3
如果我提供的文件名已经存在于数据库中,则我希望更新表格,否则我想插入一个新行。我尝试了这段代码,但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# 代码中,你不能在其中编写 SQL 语法。 - Royi Namir
你是否定义/实现了EXIST函数?你需要这样做。 - Sami
2
MERGE 是为了这个目的。 - Maheswaran Ravisankar
1
在这里使用MERGE是一个不好的选择,建议使用IF EXISTS/INSERT/UPDATE在单个批处理中完成。 - Alex K.
2
SQL注入警报 - 您不应将SQL语句串联在一起 - 而应使用参数化查询来避免SQL注入。 - marc_s
显示剩余3条评论
5个回答

24

你应该:

  • 始终在查询中使用参数,没有例外
  • 在服务器端创建一个处理 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();
    }
}

5

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

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中引入了... - Antonio
确实,MERGE是在2008版本中引入的。基于SQL:2003标准。由于问题没有指定数据库版本,因此不能假设它必须在SQL Server 2005或更早版本上工作 :) - LukStorms

1
创建一个类似于数据库中的存储过程。
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);

0

你可以用一条查询完成这个操作

在你想要声明一个 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注入……等等),这段代码是可以工作的。 - Manu Padmanabhan
1
@mr.cool,你说得对,但我们能做什么呢?这里有一些成员认为他们是正确的,我们看到那个提问者从他的问题中没有SQL注入的背景,但仍然第二次StackOverflow让我心碎。 :( - Faraz Ahmed
1
但我点了赞,因为作为新手,这段代码更容易理解。 - Manu Padmanabhan

-1
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();



    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接