允许用户删除sql表中的特定记录。问题是我想将id(自动)设置为删除后出现在数据库中的最后一个id序列... ex(删除第14个项目,当我添加另一个项目时,该项目的id不会是15,但是14,因为删除后我将ID重置为13,这是删除后的最后一个)
private void btnCanc_Click(object sender, RoutedEventArgs e)
{
sqliteCon.Open();
try
{
string Test = null;//estrazione1
SqlCommand q = new SqlCommand("DELETE FROM tabSE WHERE idSE =" + txtIDL.Text.ToString(), sqliteCon);
//string q = "DELETE FROM tabSE WHERE idSE =" + txtIDL.Text.ToString();
SqlCommand q1 = new SqlCommand("DELETE FROM tabL WHERE idL =" + txtIDL.Text.ToString(), sqliteCon);
//string q1 = "DELETE FROM tabL WHERE idL =" + txtIDL.Text.ToString();
SqlCommand q2 = new SqlCommand("DELETE FROM tabSD WHERE id =" + txtIDL.Text.ToString(), sqliteCon);
//string q2 = "DELETE FROM tabSD WHERE id =" + txtIDL.Text.ToString();
q.ExecuteNonQuery();
q1.ExecuteNonQuery();
q2.ExecuteNonQuery();
SqlCommand m = new SqlCommand("SELECT idL FROm tabL", sqliteCon);
SqlDataReader idLRdr = null;//estrazione2
idLRdr = m.ExecuteReader();//estrazione3
while (idLRdr.Read())//estrazione4
{
Test = idLRdr["idL"].ToString();//estrazione5
}
SqlCommand r = new SqlCommand("DBCC CHECKIDENT(tabL,tabSE,tabSD,RESEED,'" + Test + "')", sqliteCon);
r.ExecuteNonQuery();
SqlCommand r1 = new SqlCommand("DBCC CHECKIDENT(tabL,RESEED,'" + Test + "')", sqliteCon);
r1.ExecuteNonQuery();
SqlCommand r2 = new SqlCommand("DBCC CHECKIDENT(tabSE,RESEED,'" + Test + "')", sqliteCon);
r2.ExecuteNonQuery();
SqlCommand r3 = new SqlCommand("DBCC CHECKIDENT(tabSD,RESEED,'" + Test + "')", sqliteCon);
r3.ExecuteNonQuery();
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
MessageBox.Show("Dato Cancellato Correttamente");
sqliteCon.Close();
}
代码已改进,但它更新了表ID的值,但未更新每个表的真实ID(idL,idSE,id)(这些是我的自定义ID)
好的,我已经做了我的测试,问题是每个表的ID(idL(TABLE tabL),idSE(TABLE tabSE),id(TABLE tabSD))都没有被我的代码DBCC更新每个表(不需要定制的表)都是自动更新的...我需要更新idL,idSE,id
答案 0 :(得分:3)
当然,第一个问题是您不执行命令,但是代码中有很多可以改进的地方。首先是构建sql命令的字符串连接。这会导致解析问题以及用于入侵数据库的dangerous Sql Injection技巧。我已更改您的代码以使用参数并避免出现这些问题。
第二个改进是执行批处理命令的能力。换句话说,您可以将所有命令文本放在单个字符串中,并使用分号将每个命令文本分开。然后只执行一次命令,一切将由数据库引擎执行。
但是代码中真正的问题是 DBCC CheckIdentity RESEED 部分。这部分要求您知道将哪个值设置为新标识,因为没有下一个新值的RESEED选项仅在下一个标识值低于IDENTITY列中的当前最大值时才起作用,此外,只有当您拥有对数据库的独占访问权限(我的意思是,在您获得ID的最大值时,没有人向这些表添加记录)
sqliteCon.Open();
try
{
string sqlText = @"DELETE FROM tabStoreExec WHERE idSE = @idse;
DELETE FROM tabList WHERE idL = @idse;
DELETE FROM tabStoricoDetail WHERE id = @idse";
SqlCommand q = new SqlCommand(sqlText, sqliteCon);
q.Parameters.Add("@idse", SqlDbType.Int).Value = Convert.ToInt32(txtIDL.Text);
q.ExecuteNonQuery();
// This is the point where you change the identity.
// To minimize concurrency problems we execute a stored procedure instead
sqlText = "ResetIdentity";
q.CommandText = sqlText;
q.CommandType = CommandType.StoredProcedure;
q.Parameters.Clear();
q.ExecuteNonQuery();
MessageBox.Show("Dato Cancellato Correttamente");
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
sqliteCon.Close();
这是存储过程的可能代码,请注意,我不知道表中IDENTITY列的名称是什么。在此示例中,我始终使用 id 作为IDENTITY列的名称
create procedure ResetIdentity
as
begin
declare @maxval integer
set @maxval = (select MAX(id) from tabStoreExec);
dbcc checkident('tabStoreExec', RESEED, @maxval);
set @maxval = (select MAX(id) from tabStoricoDetail);
dbcc checkident('tabStoricoDetail', RESEED, @maxval);
set @maxval = (select MAX(id) from tabList);
dbcc checkident('tabList', RESEED, @maxval);
end
您的代码还有另一个改进,它与using statement有关,它可以创建一次性对象,例如数据库连接。此类对象的正确用法应该是这样
using(SqlConnection sqlConn = new SqlConnection(......))
{
sqlConn.Open();
.... do you database code here ....
} // This will close and dispose the connection
答案 1 :(得分:0)
我也将按照@Steve所说的去做,这里的ID是用于表(PK,FK)关系的,为什么不只是添加另一个需要使用LINQ更新的序号字段。并且您的代码缺少查询执行命令,
#include <iostream>
int main() {
const float v1 = 0.499999975;
const float v2 = 0.4999999702;
std::cout << (int)(v1+0.5) << "\n"
<< (int)(v2+0.5) << "\n";
}
con.Close();