如何在SQL中处理随机字符串键的主键存在?

时间:2016-08-03 02:10:35

标签: c# sql sql-server sql-insert

随机字符串(6个字符)用作我的SQL数据库表中的主键。但是,我不知道如何处理错误并将查询重新插入数据库。

使用另一个随机字符串键将sql查询重新插入数据库的最佳解决方案是什么? (在catch块中重新插入?)

python

上面的代码是用C#编写的,但我不认为问题只是C#。因此,欢迎另一种编程语言:)

4 个答案:

答案 0 :(得分:3)

计算随机值并针对数据库进行测试是一种缓慢/不可扩展的方法 - 它相当于猜测可用值。使用的值越多,猜测可用值的几率越大,过程变得越慢。

如果你真的不能使用Identity或Sequence或GUID,我在另一个线程中看到了一个很好的建议,就是创建一个包含" pool"独特的价值观,并使用它们。每次生成对象时,请从此表中选择并删除该行,以使该值不再可用。

请务必正确使用事务,以阻止其他并发读取器获取相同的值。

答案 1 :(得分:2)

您是否考虑过首先使用随机字符串执行SELECT查询?如果然后返回没有结果,则运行INSERT。否则,生成一个新的随机字符串,直到没有返回结果。

===

编辑代码示例。

try
{
    SqlConnection con = new SqlConnection(ConnectionString);
    con.Open();
    int count = 1;
    string key = string.Empty;

    while (count > 0)
    {
        key = RandomString(6);
        SqlCommand selectCommand = new SqlCommand("SELECT COUNT(*) FROM tableName WHERE d1 = @0", con);
        selectCommand.Parameters.Add(new SqlParameter("0", key));
        count = (int)selectCommand.ExecuteScalar();
    }

    SqlCommand insertCommand = new SqlCommand("INSERT INTO tableName(d1, d2, d3) VALUES (@0, @1, @2)", con);

    insertCommand.Parameters.Add(new SqlParameter("0", key));
    insertCommand.Parameters.Add(new SqlParameter("1", "values"));
    insertCommand.Parameters.Add(new SqlParameter("2", DateTime.Now));
    var rowCount = insertCommand.ExecuteNonQuery();


    con.Close();
    if (rowCount < 1)
    {
        label.Text = "OMG it is Fail :(";
        return false;
    }
    else
    {
        label.Text = "HEY ~~~ inserted";
        return true;
    }
}
catch (Exception ex)
{
    label.Text = ex.Message;
    return false;
}

===

老实说,我所展示的上述方法非常糟糕。它解决了您在主键中发生冲突的问题,但它并不是正确的方法。我会推荐一些改变之一:

  • 将表中的主键更改为GUID。这将允许您使用Guid.NewGuid()作为该值,您可以认为该值是唯一的。
  • 将表中的主键更改为自动递增的整数。然后,在插入的代码中,为该列提供值。这将允许数据库为您处理主键。
  • 如果必须使用随机字符串作为主键,我会在应用程序初始化期间针对所有主键对表执行查询,并将结果存储为静态HashSet<string> 。然后,当您在RandomString(int)方法中生成新的随机字符串时,请检查该HashSet以查看它是否存在。如果没有,继续插入,否则生成一个新的。

答案 2 :(得分:-1)

您可以尝试以下

将Try / Catch块放在带有标志的循环中

如果有任何错误,请在Catch块中设置标志以继续循环。

答案 3 :(得分:-2)

为什么不使用存储过程?

因此,在存储过程中生成随机密钥(使用类似GUID的东西,使用最后6个字符或类似的东西)。

然后在同一个存储过程中,在插入id之前,首先执行exists语句检查。如果ID存在,则重新生成ID,如果不存在,则插入。

所以你的c#代码只会调用那个存储过程。在c#中执行插入或任何sql语句都很糟糕,因为它很容易被sql注入。