我继承了一个项目,但我遇到SQL
错误,我不确定如何修复。
在电子商务网站上,代码会将订单发货信息插入另一个数据库表。
这是将信息插入表中的代码:
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错误:
违反PRIMARY KEY约束' PK_AC_Shipping_Addresses'。无法插入 对象' dbo.AC_Shipping_Addresses'中的重复键。重复键值 是(165863)。
从阅读类似的问题,似乎我应该在声明中声明ID。
这是对的吗?我如何调整代码来解决这个问题?
非常感谢任何帮助!
答案 0 :(得分:9)
当我尝试使用EntityFramework插入新记录时,我在恢复的数据库上遇到了同样的错误。事实证明,Indentity / Seed正在搞砸事情。
使用重新设定命令修复它。
DBCC CHECKIDENT ('[Prices]', RESEED, 4747030);GO
答案 1 :(得分:3)
非常确定pk_OrderID是AC_Shipping_Addresses的PK
您正试图通过_Order.OrderNumber
插入副本做一个
select * from AC_Shipping_Addresses where pk_OrderID = 165863;
或选择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)
答案 2 :(得分:2)
您传递给主键的值是什么(大概是“pk_OrderID”)?您可以将其设置为自动增量,然后重复该值永远不会有问题 - 数据库将负责这一点。如果您需要自己指定一个值,则需要编写代码来确定该字段的最大值,然后增加该值。
如果你有一个名为“ID”的列或者查询中没有显示的列,只要设置为自动增量就可以了 - 但它可能不是,或者你不应该得到那个错误的消息。此外,您最好还是编写一个更容易上手的查询并使用params。因为九年后的推论,如果您只是填写用户输入的值,那么您将使数据库对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
Justin想知道这是否有效:
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.
答案 3 :(得分:1)
防止插入已存在的记录。我检查数据库中是否存在ID值。对于使用IDENTITY PRIMARY KEY创建的表的示例:
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');
TABLE [dbo]的数据库输出。[人员]将是:
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
}
答案 4 :(得分:0)
可能有几件事情导致这种情况,这在某种程度上取决于您在数据库中设置的内容。
首先,您可以在表格中使用PK,这也是另一个表格的FK,使关系为1-1。在这种情况下,您可能需要进行更新而不是插入。如果你真的只能有一个订单的地址记录,这可能就是正在发生的事情。
接下来,您可以使用某种手动过程来提前确定ID。这些手动过程的问题在于它们可以创建竞争条件,其中两个记录获取相同的最后一个id并将其递增一个然后第二个记录可以; t insert。
第三,你查询因为它被发送到数据库可能会创建两个记录。要确定是否是这种情况,请运行Profiler以准确查看要发送的SQL代码,如果ti是select而不是values子句,则运行select并查看是否由于连接而导致某些记录被复制。即使在你动态创建代码时,第一个故障排除步骤仍然是运行Profiler,看看发送的是你期望发送的内容。
答案 5 :(得分:0)
不是OP的答案,但由于这是在Google中为我弹出的第一个问题,因此Id还想补充一点,搜索此内容的用户可能需要重新设置表格,对我而言就是这样
DBCC CHECKIDENT(tablename)
答案 6 :(得分:0)
请确保您的表中没有主键值与查询中的主键ID相同的行。