需要帮助改进 SQL DELETE 性能
Need help improving SQL DELETE performance
我有两个关系,Customer 和 Adress。首先,我没有修改数据库的权限(比如为客户和地址创建新的比率)。
我需要的是,给定状态列表,删除具有与该状态相关的 Adress1 或 Adress2 的客户。
我在下面做的事情很慢,所以任何帮助将不胜感激。
foreach (State state in listOfStates)
{
query =
"DELETE FROM CUSTOMER
WHERE EXISTS (
SELECT * FROM ADRESS
WHERE CUSTOMER.ADRESS1 = ADRESS.ID
AND STATE = " + state + ")";
cmd.CommandText = query;
cmd.ExecuteNonQuery();
query =
"DELETE FROM CUSTOMER
WHERE EXISTS (
SELECT * FROM ADRESS
WHERE CUSTOMER.ADRESS2 = ADRESS.ID
AND STATE = " + state + ")";
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
Customer
+----------+---------+---------+--+
| Name | Adress1 | Adress2 | |
+----------+---------+---------+--+
| John Doe | 1 | 2 | |
| Victor | 3 | 4 | |
| Renat | 5 | 6 | |
+----------+---------+---------+--+
Adress
+----+--------+------+------------+
| ID | Street | City | State |
+----+--------+------+------------+
| 1 | xxx | xxx | California |
| 2 | xxx | xxx | Florida |
| 3 | xxx | xxx | California |
| 4 | xxx | xxx | Ohio |
| 5 | xxx | xxx | Virginia |
| 6 | xxx | xxx | Colorado |
+----+--------+------+------------+
我建议您为各州建立一个 IN 子句。如果您的 listOfStates 是 List<string>
,这将是:
string states = "'" + string.Join("','", listOfStates) + "'";
(这将导致类似 'Arizona','Kentucky','Tennessee'
的结果,即 comma-separated 字符串,所有状态都用单引号引起来。)
如果 listOfStates 不是 List<string>
,则调整以上内容以满足您的 collection 类型,例如
string states = "'" + string.Join("','", listOfStates.Select(state => state.Name)) + "'";
然后 运行 所有状态的单个删除语句:
query =
"DELETE FROM customer
WHERE EXISTS (
SELECT * FROM adress
WHERE adress.id IN (customer.adress1, customer.adress2)
AND adress.state IN (" + states + "))";
cmd.CommandText = query;
cmd.ExecuteNonQuery();
根据我使用 Access 的经验,联接通常比 WHERE EXISTS 子句快得多。
这应该可以通过复合 JOIN 来实现。以下是航空代码,但应该可以使用。
Access 喜欢在重要的 JOIN 子句中使用大量括号。
SELECT c.*
FROM CUSTOMER c
INNER JOIN ADRESS a
ON ((c.ADRESS1 = a.ID OR c.ADRESS2 = a.ID)
AND (a.STATE = <state>)
)
如果上述方法有效,只需将 SELECT 替换为 DELETE。
您也可以结合 Thorsten 的建议:
AND (a.STATE IN ('state1', 'state2'))
我有两个关系,Customer 和 Adress。首先,我没有修改数据库的权限(比如为客户和地址创建新的比率)。 我需要的是,给定状态列表,删除具有与该状态相关的 Adress1 或 Adress2 的客户。 我在下面做的事情很慢,所以任何帮助将不胜感激。
foreach (State state in listOfStates)
{
query =
"DELETE FROM CUSTOMER
WHERE EXISTS (
SELECT * FROM ADRESS
WHERE CUSTOMER.ADRESS1 = ADRESS.ID
AND STATE = " + state + ")";
cmd.CommandText = query;
cmd.ExecuteNonQuery();
query =
"DELETE FROM CUSTOMER
WHERE EXISTS (
SELECT * FROM ADRESS
WHERE CUSTOMER.ADRESS2 = ADRESS.ID
AND STATE = " + state + ")";
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
Customer
+----------+---------+---------+--+
| Name | Adress1 | Adress2 | |
+----------+---------+---------+--+
| John Doe | 1 | 2 | |
| Victor | 3 | 4 | |
| Renat | 5 | 6 | |
+----------+---------+---------+--+
Adress
+----+--------+------+------------+
| ID | Street | City | State |
+----+--------+------+------------+
| 1 | xxx | xxx | California |
| 2 | xxx | xxx | Florida |
| 3 | xxx | xxx | California |
| 4 | xxx | xxx | Ohio |
| 5 | xxx | xxx | Virginia |
| 6 | xxx | xxx | Colorado |
+----+--------+------+------------+
我建议您为各州建立一个 IN 子句。如果您的 listOfStates 是 List<string>
,这将是:
string states = "'" + string.Join("','", listOfStates) + "'";
(这将导致类似 'Arizona','Kentucky','Tennessee'
的结果,即 comma-separated 字符串,所有状态都用单引号引起来。)
如果 listOfStates 不是 List<string>
,则调整以上内容以满足您的 collection 类型,例如
string states = "'" + string.Join("','", listOfStates.Select(state => state.Name)) + "'";
然后 运行 所有状态的单个删除语句:
query =
"DELETE FROM customer
WHERE EXISTS (
SELECT * FROM adress
WHERE adress.id IN (customer.adress1, customer.adress2)
AND adress.state IN (" + states + "))";
cmd.CommandText = query;
cmd.ExecuteNonQuery();
根据我使用 Access 的经验,联接通常比 WHERE EXISTS 子句快得多。
这应该可以通过复合 JOIN 来实现。以下是航空代码,但应该可以使用。
Access 喜欢在重要的 JOIN 子句中使用大量括号。
SELECT c.*
FROM CUSTOMER c
INNER JOIN ADRESS a
ON ((c.ADRESS1 = a.ID OR c.ADRESS2 = a.ID)
AND (a.STATE = <state>)
)
如果上述方法有效,只需将 SELECT 替换为 DELETE。
您也可以结合 Thorsten 的建议:
AND (a.STATE IN ('state1', 'state2'))