查询外键不同结果

huangapple go评论75阅读模式
英文:

Querying foreign keys different results

问题

I am writing some code that will disable and enable foreign keys on a table. It appears to run fine. When I check the status of the Foreign key immediately executing the code the status appears to be unchanged with one query and changed with a different query.

我正在编写一些代码,用于在表上禁用和启用外键。代码似乎运行正常。当我立即执行代码并检查外键的状态时,一个查询显示状态未更改,而另一个查询显示状态已更改。

I can't seem to figure out what the problem is and was hoping someone can help me out and explain this anomaly and or suggest a fix to my code.

我似乎无法弄清楚问题出在哪里,希望有人可以帮助我解释这个异常或建议修复我的代码。

Below is my test CASE along with sample data to show what I have done.

以下是我的测试用例以及示例数据,以展示我所做的事情。

英文:

I am writing some code that will disable and enable foreign keys on a table. It appears to run fine. When I check the status of the Foreign key immediately executing the code the status appears to be unchanged with one query and changed with a different query.

I can't seem to figure out what the problem is and was hoping someone can help me out and explain this anomaly and or suggest a fix to my code.

Below is my test CASE along with sample data to show what I have done.

  1. CREATE TABLE customers
  2. (CUSTOMER_ID, FIRST_NAME, LAST_NAME) AS
  3. SELECT 1, 'Faith', 'Mazzarone' FROM DUAL UNION ALL
  4. SELECT 2, 'Lisa', 'Saladino' FROM DUAL UNION ALL
  5. SELECT 3, 'Micheal', 'Palmice' FROM DUAL UNION ALL
  6. SELECT 4, 'Joseph', 'Zaza' FROM DUAL UNION ALL
  7. SELECT 5, 'Jerry', 'Torchiano' FROM DUAL;
  8. ALTER TABLE customers
  9. ADD CONSTRAINT customers_pk PRIMARY KEY (customer_id);
  10. CREATE TABLE items
  11. (PRODUCT_ID, PRODUCT_NAME, PRICE) AS
  12. SELECT 100, 'Black Shoes', 79.99 FROM DUAL UNION ALL
  13. SELECT 101, 'Brown Pants', 111.99 FROM DUAL UNION ALL
  14. SELECT 102, 'White Shirt', 10.99 FROM DUAL;
  15. ALTER TABLE items
  16. ADD CONSTRAINT items_pk PRIMARY KEY (product_id);
  17. create table purchases(
  18. ORDER_ID NUMBER GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
  19. customer_id number,
  20. PRODUCT_ID NUMBER,
  21. QUANTITY NUMBER,
  22. purchase_date timestamp
  23. );
  24. insert into purchases (customer_id, product_id, quantity, purchase_date)
  25. SELECT 3, 102, 4,TIMESTAMP '2022-12-22 21:44:35' + NUMTODSINTERVAL ( LEVEL * 2, 'DAY') FROM dual
  26. CONNECT BY LEVEL <= 15 UNION ALL
  27. select 1, 101,3, date '2023-03-29' + level * interval '2' day from dual
  28. connect by level <= 12
  29. union all
  30. select 2, 101,2, date '2023-01-15' + level * interval '8' hour from dual
  31. connect by level <= 15
  32. union all
  33. select 2, 102,2,date '2023-04-13' + level * interval '1 1' day to hour from dual
  34. connect by level <= 11
  35. union all
  36. select 3, 101,2, date '2023-02-01' + level * interval '1 05:03' day to minute from dual
  37. connect by level <= 10
  38. union all
  39. select 3, 101,1, date '2023-04-22' + level * interval '23' hour from dual
  40. connect by level <= 23
  41. union all
  42. select 3, 100,1, date '2022-03-01' + level * interval '1 00:23:05' day to second from dual
  43. connect by level <= 15
  44. union all
  45. select 4, 102,1, date '2023-01-01' + level * interval '5' hour from dual
  46. connect by level <= 60;
  47. ALTER TABLE purchases
  48. ADD CONSTRAINT order_pk PRIMARY KEY (order_id);
  49. ALTER TABLE purchases ADD CONSTRAINT customers_fk FOREIGN KEY (customer_id) REFERENCES customers(customer_id);
  50. ALTER TABLE purchases ADD CONSTRAINT items_fk FOREIGN KEY (PRODUCT_ID) REFERENCES items(product_id);
  51. /* both queries fine here */
  52. SELECT '"' || a.owner
  53. || '"."'
  54. || a.table_name
  55. || '"' AS full_table_name,
  56. a.constraint_name,
  57. b.status
  58. FROM user_constraints a
  59. JOIN user_constraints b
  60. ON ( a.r_constraint_name = b.constraint_name
  61. AND a.r_owner = b.owner )
  62. WHERE a.constraint_type = 'R'
  63. AND b.status = 'ENABLED'
  64. ORDER BY 1
  65. FULL_TABLE_NAME
  66. CONSTRAINT_NAME STATUS
  67. "XXX"."PURCHASES" ITEMS_FK ENABLED
  68. "XXX"."PURCHASES" CUSTOMERS_FK ENABLED
  69. select owner, table_name, r_constraint_name, status
  70. from user_constraints
  71. where constraint_type = 'R';
  72. OWNER TABLE_NAME R_CONSTRAINT_NAME STATUS
  73. XXX PURCHASES CUSTOMERS_PK ENABLED
  74. XXX PURCHASES ITEMS_PK ENABLED
  75. /* disable foreign keys */
  76. BEGIN
  77. FOR r IN (
  78. SELECT '"' || a.owner
  79. || '"."'
  80. || a.table_name
  81. || '"' AS full_table_name,
  82. a.constraint_name
  83. FROM user_constraints a
  84. JOIN user_constraints b
  85. ON ( a.r_constraint_name = b.constraint_name
  86. AND a.r_owner = b.owner )
  87. WHERE a.constraint_type = 'R'
  88. AND b.status = 'ENABLED'
  89. ORDER BY 1 ) LOOP
  90. dbms_output.put_line ( 'Disable the constraint ' || r.constraint_name ||' (on table ' || r.full_table_name || ')' ) ;
  91. dbms_utility.exec_ddl_statement ( 'alter table ' || r.full_table_name || ' disable constraint ' || r.constraint_name ) ;
  92. END LOOP ;
  93. END ;
  94. /
  95. Statement processed.
  96. Disable the constraint ITEMS_FK (on table "XXX"."PURCHASES")
  97. Disable the constraint CUSTOMERS_FK (on table "XXX"."PURCHASES")
  98. /* status different between queries ????. Problem here!!!
  99. */
  100. SELECT '"' || a.owner
  101. || '"."'
  102. || a.table_name
  103. || '"' AS full_table_name,
  104. a.constraint_name,
  105. b.status
  106. FROM user_constraints a
  107. JOIN user_constraints b
  108. ON ( a.r_constraint_name = b.constraint_name
  109. AND a.r_owner = b.owner )
  110. WHERE a.constraint_type = 'R'
  111. AND b.status = 'ENABLED'
  112. ORDER BY 1
  113. FULL_TABLE_NAME
  114. CONSTRAINT_NAME STATUS
  115. "XXX"."PURCHASES" ITEMS_FK ENABLED
  116. "XXX"."PURCHASES" CUSTOMERS_FK ENABLED
  117. select owner, table_name, r_constraint_name, status
  118. from user_constraints
  119. where constraint_type = 'R';
  120. OWNER TABLE_NAME R_CONSTRAINT_NAME STATUS
  121. XXX PURCHASES CUSTOMERS_PK DISABLED
  122. XXX PURCHASES ITEMS_PK DISABLED

答案1

得分: 1

以下是翻译好的部分:

"Those are 2 different queries and they are correctly showing the results."
这是两个不同的查询,它们正确显示了结果。

"you're assuming that you are seeing the status of the foreign key constraint but... that is not the case. Add some additional columns to the query and it all becomes clear."
你假设你看到了外键约束的状态,但事实并非如此。向查询添加一些额外的列,一切都会变得清晰。

"The column b.status is the status of the referenced constraint, not the status of the foreign key constraint. The referenced constraint is the primary key value of the 2 tables and the status is "enabled" since you didn't touch those...."
列b.status是引用约束的状态,而不是外键约束的状态。引用约束是两个表的主键值,状态为"enabled",因为你没有对它们进行更改。

"To find referenced constraints, just use that other query you are showing"
要查找引用约束,只需使用你显示的另一个查询。

"But... I would not take this route. What if there is a constraint that is already disabled before you run your script ? That constraint will then be enabled again by your "enable" script. Much safer to create a table where you store the name of the constraints you have disabled so you know which ones to enable again afterwards."
但是...我不建议采取这种方法。如果在运行脚本之前已经有一个已禁用的约束呢?那么你的"enable"脚本将重新启用该约束。更安全的做法是创建一个表,其中存储你已禁用的约束的名称,这样你就知道哪些需要在之后重新启用。

英文:

Those are 2 different queries and they are correctly showing the results.
you're assuming that you are seeing the status of the foreign key constraint but... that is not the case. Add some additional columns to the query and it all becomes clear.

  1. SELECT '"' || a.owner
  2. || '"."'
  3. || a.table_name
  4. || '"' AS full_table_name,
  5. a.constraint_name,
  6. a.status,
  7. b.constraint_name,
  8. b.table_name,
  9. b.status
  10. FROM user_constraints a
  11. JOIN user_constraints b
  12. ON ( a.r_constraint_name = b.constraint_name
  13. AND a.r_owner = b.owner )
  14. WHERE a.constraint_type = 'R'
  15. AND b.status = 'ENABLED'
  16. ORDER BY 1;
  17. "ACDC"."PURCHASES" ITEMS_FK DISABLED ITEMS_PK ITEMS ENABLED
  18. "ACDC"."PURCHASES" CUSTOMERS_FK. DISABLED CUSTOMERS_PK CUSTOMERS ENABLED

The column b.status is the status of the referenced constraint, not the status of the foreign key constraint. The referenced constraint is the primary key value of the 2 tables and the status is "enabled" since you didn't touch those....

To find referenced constraints, just use that other query you are showing

  1. select owner, table_name, r_constraint_name, status
  2. from user_constraints
  3. where constraint_type = 'R';

But... I would not take this route. What if there is a constraint that is already disabled before you run your script ? That constraint will then be enabled again by your "enable" script. Much safer to create a table where you store the name of the constraints you have disabled so you know which ones to enable again afterwards.

huangapple
  • 本文由 发表于 2023年5月10日 23:50:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76220433.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定