在电子商务网站上,此代码将订单运输信息插入另一个数据库:
string sql = "INSERT INTO AC_Shipping_Addresses
(pk_OrderID, FullName, Company, Address1, Address2, City, Province, PostalCode, CountryCode, Phone, Email, ShipMethod, Charge_Freight, Charge_Subtotal)
VALUES (" + _Order.OrderNumber;
sql += ", '" + _Order.Shipments[0].ShipToFullName.Replace("'", "''") + "'";
if (_Order.Shipments[0].ShipToCompany == "")
{
sql += ", '" + _Order.Shipments[0].ShipToFullName.Replace("'", "''") + "'";
}
else
{
sql += ", '" + _Order.Shipments[0].ShipToCompany.Replace("'", "''") + "'";
}
sql += ", '" + _Order.Shipments[0].Address.Address1.Replace("'", "''") + "'";
sql += ", '" + _Order.Shipments[0].Address.Address2.Replace("'", "''") + "'";
sql += ", '" + _Order.Shipments[0].Address.City.Replace("'", "''") + "'";
sql += ", '" + _Order.Shipments[0].Address.Province.Replace("'", "''") + "'";
sql += ", '" + _Order.Shipments[0].Address.PostalCode.Replace("'", "''") + "'";
sql += ", '" + _Order.Shipments[0].Address.Country.Name.Replace("'", "''") + "'";
sql += ", '" + _Order.Shipments[0].Address.Phone.Replace("'", "''") + "'";
if (_Order.Shipments[0].ShipToEmail == "")
{
sql += ",'" + _Order.BillToEmail.Replace("'", "''") + "'";
}
else
{
sql += ",'" + _Order.Shipments[0].ShipToEmail.Replace("'", "''") + "'";
}
sql += ", '" + _Order.Shipments[0].ShipMethod.Name.Replace("'", "''") + "'";
sql += ", " + shippingAmount;
sql += ", " + _Order.ProductSubtotal.ToString() + ")";
bll.dbUpdate(sql);
它正在工作,但它也输出以下 SQL 错误:
Violation of PRIMARY KEY constraint 'PK_AC_Shipping_Addresses'. Cannot insert duplicate key in object 'dbo.AC_Shipping_Addresses'. The duplicate key value is (165863).
我需要在声明中申报ID吗?
我该如何调整代码来解决这个问题?
使用重新设定种子命令修复了该问题。
DBCC CHECKIDENT ('[Prices]', RESEED, 4747030);GO
pk_OrderID
是
AC_Shipping_Addresses
的PK
并且您正在尝试通过 _Order.OrderNumber
插入重复项?做一个
select * from AC_Shipping_Addresses where pk_OrderID = 165863;
或select count(*)
....很确定您会返回一行。
它告诉您您已经在使用
pk_OrderID = 165863
并且不能再有具有该值的行。如果想有一行就不插入
insert into table (pk, value)
select 11 as pk, 'val' as value
where not exists (select 1 from table where pk = 11)
如果您有一个名为“ID”的列或未在查询中显示的列,只要将其设置为自动增量就可以了 - 但它可能不是,或者您不应该收到该错误消息。另外,您最好编写一个更直观的查询并使用参数。正如这位九岁小伙子推断的那样,如果您只是简单地输入用户输入的值,您的数据库就会受到 SQL 注入攻击。例如,您可以有这样的方法:
internal static int GetItemIDForUnitAndItemCode(string qry, string unit, string itemCode)
{
int itemId;
using (SqlConnection sqlConn = new SqlConnection(ReportRunnerConstsAndUtils.CPSConnStr))
{
using (SqlCommand cmd = new SqlCommand(qry, sqlConn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("@Unit", SqlDbType.VarChar, 25).Value = unit;
cmd.Parameters.Add("@ItemCode", SqlDbType.VarChar, 25).Value = itemCode;
sqlConn.Open();
itemId = Convert.ToInt32(cmd.ExecuteScalar());
}
}
return itemId;
}
...这样称呼:
int itemId = SQLDBHelper.GetItemIDForUnitAndItemCode(GetItemIDForUnitAndItemCodeQuery, _unit, itemCode);
你不必这样做,但我单独存储查询:
public static readonly String GetItemIDForUnitAndItemCodeQuery = "SELECT PoisonToe FROM Platypi WHERE Unit = @Unit AND ItemCode = @ItemCode";
您可以通过(伪代码)验证您是否不打算插入已经存在的值:
bool alreadyExists = IDAlreadyExists(query, value) > 0;
查询类似于“SELECT COUNT FROM TABLE WHERE BLA = @CANDIDATEIDVAL”,该值是您可能要插入的 ID:
if (alreadyExists) // keep inc'ing and checking until false, then use that id value
贾斯汀想知道这是否有效:
string exists = "SELECT 1 from AC_Shipping_Addresses where pk_OrderID = " _Order.OrderNumber; if (exists > 0)...
对我来说似乎有用的是:
string existsQuery = string.format("SELECT 1 from AC_Shipping_Addresses where pk_OrderID = {0}", _Order.OrderNumber);
// Or, better yet:
string existsQuery = "SELECT COUNT(*) from AC_Shipping_Addresses where pk_OrderID = @OrderNumber";
// Now run that query after applying a value to the OrderNumber query param (use code similar to that above); then, if the result is > 0, there is such a record.
DBCC CHECKIDENT(tablename)
CREATE TABLE [dbo].[Persons] (
ID INT IDENTITY(1,1) PRIMARY KEY,
LastName VARCHAR(40) NOT NULL,
FirstName VARCHAR(40)
);
当 JANE DOE 和 JOE BROWN 已存在于数据库中时。
SET IDENTITY_INSERT [dbo].[Persons] OFF;
INSERT INTO [dbo].[Persons] (FirstName,LastName)
VALUES ('JANE','DOE');
INSERT INTO Persons (FirstName,LastName)
VALUES ('JOE','BROWN');
表 [dbo].[Persons] 的数据库输出将是:
ID LastName FirstName
1 DOE Jane
2 BROWN JOE
我会检查是否应该更新现有记录或插入新记录。如以下 JAVA 示例:
int NewID = 1;
boolean IdAlreadyExist = false;
// Using SQL database connection
// STEP 1: Set property
System.setProperty("java.net.preferIPv4Stack", "true");
// STEP 2: Register JDBC driver
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// STEP 3: Open a connection
try (Connection conn1 = DriverManager.getConnection(DB_URL, USER,pwd) {
conn1.setAutoCommit(true);
String Select = "select * from Persons where ID = " + ID;
Statement st1 = conn1.createStatement();
ResultSet rs1 = st1.executeQuery(Select);
// iterate through the java resultset
while (rs1.next()) {
int ID = rs1.getInt("ID");
if (NewID==ID) {
IdAlreadyExist = true;
}
}
conn1.close();
} catch (SQLException e1) {
System.out.println(e1);
}
if (IdAlreadyExist==false) {
//Insert new record code here
} else {
//Update existing record code here
}
为了实现这个目标我
所以在执行这个查询之前你必须检查是否有记录。
首先,您可以在表中使用 PK,该 PK 也是另一个表的 FK,从而形成 1-1 关系。在这种情况下,您可能需要执行更新而不是插入。如果您确实只能拥有一个订单的地址记录,这可能就是正在发生的情况。
接下来您可以使用某种手动过程来提前确定 id。这些手动过程的问题在于,它们可能会产生竞争条件,其中两条记录会重复相同的最后一个 id,并将其加一,然后第二条记录无法插入。
第三,您的查询在发送到数据库时可能会创建两条记录。要确定是否是这种情况,请运行 Profiler 以查看您正在发送的 SQL 代码,以及 ti 是否是 select 而不是值子句,然后运行 select 并查看是否由于连接而获得了一些要重复的记录。即使您像这样动态创建代码,第一个故障排除步骤始终是运行 Profiler 并查看发送的内容是否是您期望发送的内容。