{"id":122531,"date":"2026-11-05T03:08:39","date_gmt":"2026-11-04T19:08:39","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/122531.html"},"modified":"2026-11-05T03:08:39","modified_gmt":"2026-11-04T19:08:39","slug":"sql-designing-efficient-sql-select-queries-using-oracel-21c","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/122531.html","title":{"rendered":"sql: Designing Efficient SQL SELECT Queries using Oracel 21c"},"content":{"rendered":"<p>        \/* MD \/ \u5bcc\u6587\u672c\u4e2d\u7684 .toc\uff08\u542b\u535a\u5ba2\u56ed\u642c\u5bb6\u7b49\u5d4c\u5957\u7ed3\u6784\uff09\uff1b.toc-box \u5728\u4fa7\u680f\uff0c\u4e0d\u53d7\u5f71\u54cd *\/<br \/>\n        #content_views .toc,<br \/>\n        \/* \u7f16\u8f91\u5668\u5e38\u5728\u76ee\u5f55\u524d\u540e\u63d2\u5165\u7a7a p\uff08:empty \u4ecd\u5360 20px\uff09\uff0c\u4e00\u5e76\u53bb\u6389\u907f\u514d\u9876\u7a7a\u9699 *\/<br \/>\n        #content_views.markdown_views &gt; p:empty:has(+ .toc),<br \/>\n        #content_views.markdown_views &gt; .toc + p:empty,<br \/>\n        \/* \u5bcc\u6587\u672c\u65e7\u7248\u76ee\u5f55\u6807\u8bb0 *\/<br \/>\n        #content_views.htmledit_views #main-toc,<br \/>\n        #content_views.htmledit_views #hr-toc,<br \/>\n        #content_views.htmledit_views p[id*=\\&#8221;-toc\\&#8221;] {<br \/>\n          display: none !important;<br \/>\n        }<br \/>\n        \/* \u76ee\u5f55\u53bb\u6389\u540e\uff0c\u7d27\u8ddf\u7684\u9996\u4e2a\u6807\u9898\u4e0d\u518d\u591a\u51fa\u4e00\u5757\u4e0a\u8fb9\u8ddd *\/<br \/>\n        #content_views.markdown_views &gt; .toc + h1,<br \/>\n        #content_views.markdown_views &gt; .toc + h2,<br \/>\n        #content_views.markdown_views &gt; .toc + h3,<br \/>\n        #content_views.markdown_views &gt; .toc + h4,<br \/>\n        #content_views.markdown_views &gt; .toc + p:empty + h1,<br \/>\n        #content_views.markdown_views &gt; .toc + p:empty + h2,<br \/>\n        #content_views.markdown_views &gt; .toc + p:empty + h3,<br \/>\n        #content_views.markdown_views &gt; .toc + p:empty + h4 {<br \/>\n          margin-top: 0 !important;<br \/>\n        }<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; Oracle 21c : Dynamic Query Building in SQL<br \/>\n&#8212; Techniques, Security, and Best Practices<br \/>\n&#8212; Safe dynamic SQL (parameterized queries, stored procedures, runtime<br \/>\n&#8212; filters, SQL-injection controls) for an international jewelry<br \/>\n&#8212; mid-platform spanning OA\/ERP\/CRM\/HRM\/MES\/SCM\/WMS\/KMS.<br \/>\n&#8212;<br \/>\n&#8212; Series topic #21. Self-contained &#043; idempotent. 17 self-checks.<br \/>\n&#8212; Conventions (learned across the 21-topic series):<br \/>\n&#8212;   * All object names start with a LETTER (DQ_); Oracle rejects &#039;_&#039;-leading<br \/>\n&#8212;     unquoted identifiers with ORA-00911.<br \/>\n&#8212;   * PROMPT \/ comments are pure ASCII.<br \/>\n&#8212;   * Password lives only in the shell $P variable, never in this file.<br \/>\n&#8212;   * Cleanup loop wraps each DROP in an inner EXCEPTION handler so a<br \/>\n&#8212;     transient lock on one object never aborts the rest.<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\nSET ECHO OFF FEED OFF PAGES 0 SERVEROUT ON SIZE 1000000 LINES 200 DEFINE OFF<br \/>\nWHENEVER SQLERROR CONTINUE<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; 1. Idempotent cleanup<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\nDECLARE<br \/>\n  PROCEDURE ddrop(p_sql VARCHAR2) IS<br \/>\n  BEGIN<br \/>\n    EXECUTE IMMEDIATE p_sql;<br \/>\n  EXCEPTION<br \/>\n    WHEN OTHERS THEN NULL;   &#8212; object may not exist \/ briefly locked<br \/>\n  END;<br \/>\nBEGIN<br \/>\n  FOR r IN (SELECT table_name FROM user_tables WHERE table_name LIKE &#039;DQ%&#039;) LOOP<br \/>\n    ddrop(&#039;DROP TABLE &#039;||r.table_name||&#039; CASCADE CONSTRAINTS PURGE&#039;);<br \/>\n  END LOOP;<br \/>\n  FOR r IN (SELECT object_name, object_type FROM user_objects<br \/>\n             WHERE object_name LIKE &#039;DQ%&#039;<br \/>\n               AND object_type IN (&#039;FUNCTION&#039;,&#039;PROCEDURE&#039;,&#039;PACKAGE&#039;,&#039;PACKAGE BODY&#039;,&#039;VIEW&#039;,&#039;SEQUENCE&#039;,&#039;TYPE&#039;)) LOOP<br \/>\n    ddrop(&#039;DROP &#039;||r.object_type||&#039; &#039;||r.object_name);<br \/>\n  END LOOP;<br \/>\n  ddrop(&#039;DROP TABLE dq_val PURGE&#039;);<br \/>\n  BEGIN DELETE FROM plan_table WHERE statement_id&#061;&#039;dq_p&#039;; COMMIT; EXCEPTION WHEN OTHERS THEN NULL; END;<br \/>\nEND;<br \/>\n\/<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; 2. Dimensions: 8 business domains &#043; 10 currencies &#043; 12 regions<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\nCREATE TABLE dq_domain (<br \/>\n  domain_id NUMBER PRIMARY KEY,<br \/>\n  code VARCHAR2(10) UNIQUE,<br \/>\n  name VARCHAR2(40)<br \/>\n);<br \/>\nINSERT INTO dq_domain VALUES (1,&#039;OA&#039;,&#039;Office Automation&#039;);<br \/>\nINSERT INTO dq_domain VALUES (2,&#039;ERP&#039;,&#039;Enterprise Resource Planning&#039;);<br \/>\nINSERT INTO dq_domain VALUES (3,&#039;CRM&#039;,&#039;Customer Relationship Mgmt&#039;);<br \/>\nINSERT INTO dq_domain VALUES (4,&#039;HRM&#039;,&#039;Human Resource Mgmt&#039;);<br \/>\nINSERT INTO dq_domain VALUES (5,&#039;MES&#039;,&#039;Manufacturing Execution&#039;);<br \/>\nINSERT INTO dq_domain VALUES (6,&#039;SCM&#039;,&#039;Supply Chain Mgmt&#039;);<br \/>\nINSERT INTO dq_domain VALUES (7,&#039;WMS&#039;,&#039;Warehouse Mgmt&#039;);<br \/>\nINSERT INTO dq_domain VALUES (8,&#039;KMS&#039;,&#039;Knowledge Mgmt&#039;);<\/p>\n<p>CREATE TABLE dq_currency (<br \/>\n  cur_code VARCHAR2(3) PRIMARY KEY,<br \/>\n  name VARCHAR2(30),<br \/>\n  rate_to_usd NUMBER<br \/>\n);<br \/>\nINSERT INTO dq_currency VALUES (&#039;USD&#039;,&#039;US Dollar&#039;,1);<br \/>\nINSERT INTO dq_currency VALUES (&#039;EUR&#039;,&#039;Euro&#039;,1.08);<br \/>\nINSERT INTO dq_currency VALUES (&#039;GBP&#039;,&#039;Pound&#039;,1.27);<br \/>\nINSERT INTO dq_currency VALUES (&#039;JPY&#039;,&#039;Yen&#039;,0.0067);<br \/>\nINSERT INTO dq_currency VALUES (&#039;CNY&#039;,&#039;Yuan&#039;,0.14);<br \/>\nINSERT INTO dq_currency VALUES (&#039;HKD&#039;,&#039;HK Dollar&#039;,0.128);<br \/>\nINSERT INTO dq_currency VALUES (&#039;AUD&#039;,&#039;Aussie&#039;,0.66);<br \/>\nINSERT INTO dq_currency VALUES (&#039;BRL&#039;,&#039;Real&#039;,0.18);<br \/>\nINSERT INTO dq_currency VALUES (&#039;INR&#039;,&#039;Rupee&#039;,0.012);<br \/>\nINSERT INTO dq_currency VALUES (&#039;AED&#039;,&#039;Dirham&#039;,0.27);<br \/>\nINSERT INTO dq_currency VALUES (&#039;SGD&#039;,&#039;Sing Dollar&#039;,0.74);<br \/>\nINSERT INTO dq_currency VALUES (&#039;ZAR&#039;,&#039;Rand&#039;,0.054);<\/p>\n<p>CREATE TABLE dq_region (<br \/>\n  region_id NUMBER PRIMARY KEY,<br \/>\n  region_name VARCHAR2(30),<br \/>\n  country VARCHAR2(30),<br \/>\n  tz_name VARCHAR2(40),<br \/>\n  cur_code VARCHAR2(3),<br \/>\n  hub_lon NUMBER,<br \/>\n  hub_lat NUMBER,<br \/>\n  CONSTRAINT fk_dqreg_cur FOREIGN KEY(cur_code) REFERENCES dq_currency(cur_code)<br \/>\n);<br \/>\nINSERT INTO dq_region VALUES (1,&#039;North America&#039;,&#039;USA&#039;,&#039;America\/New_York&#039;,&#039;USD&#039;,-74.0,40.7);<br \/>\nINSERT INTO dq_region VALUES (2,&#039;Western Europe&#039;,&#039;Germany&#039;,&#039;Europe\/Berlin&#039;,&#039;EUR&#039;,13.4,52.5);<br \/>\nINSERT INTO dq_region VALUES (3,&#039;UK &amp; Ireland&#039;,&#039;UK&#039;,&#039;Europe\/London&#039;,&#039;GBP&#039;,-0.13,51.5);<br \/>\nINSERT INTO dq_region VALUES (4,&#039;Japan&#039;,&#039;Japan&#039;,&#039;Asia\/Tokyo&#039;,&#039;JPY&#039;,139.7,35.7);<br \/>\nINSERT INTO dq_region VALUES (5,&#039;China&#039;,&#039;China&#039;,&#039;Asia\/Shanghai&#039;,&#039;CNY&#039;,121.5,31.2);<br \/>\nINSERT INTO dq_region VALUES (6,&#039;Hong Kong&#039;,&#039;Hong Kong&#039;,&#039;Asia\/Hong_Kong&#039;,&#039;HKD&#039;,114.2,22.3);<br \/>\nINSERT INTO dq_region VALUES (7,&#039;Australia&#039;,&#039;Australia&#039;,&#039;Australia\/Sydney&#039;,&#039;AUD&#039;,151.2,-33.9);<br \/>\nINSERT INTO dq_region VALUES (8,&#039;Brazil&#039;,&#039;Brazil&#039;,&#039;America\/Sao_Paulo&#039;,&#039;BRL&#039;,-46.6,-23.5);<br \/>\nINSERT INTO dq_region VALUES (9,&#039;India&#039;,&#039;India&#039;,&#039;Asia\/Kolkata&#039;,&#039;INR&#039;,77.2,28.6);<br \/>\nINSERT INTO dq_region VALUES (10,&#039;UAE&#039;,&#039;UAE&#039;,&#039;Asia\/Dubai&#039;,&#039;AED&#039;,55.3,25.2);<br \/>\nINSERT INTO dq_region VALUES (11,&#039;Singapore&#039;,&#039;Singapore&#039;,&#039;Asia\/Singapore&#039;,&#039;SGD&#039;,103.8,1.35);<br \/>\nINSERT INTO dq_region VALUES (12,&#039;South Africa&#039;,&#039;South Africa&#039;,&#039;Africa\/Johannesburg&#039;,&#039;ZAR&#039;,28.0,-26.2);<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; 3. Main tables<br \/>\n&#8212;    dq_site : 6000 branch\/service points across 8 domains, 12 regions<br \/>\n&#8212;    dq_txn  : 12000 transactions, INTERVAL-partitioned by local_day<br \/>\n&#8212;              (partition pruning is key at trillion scale)<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\nCREATE TABLE dq_site (<br \/>\n  site_id NUMBER PRIMARY KEY,<br \/>\n  system_code VARCHAR2(10),<br \/>\n  region_id NUMBER,<br \/>\n  site_name VARCHAR2(40),<br \/>\n  country VARCHAR2(30),<br \/>\n  cur_code VARCHAR2(3),<br \/>\n  amount_usd NUMBER(14,2),<br \/>\n  amount_orig NUMBER(14,2),<br \/>\n  created_utc TIMESTAMP WITH TIME ZONE,<br \/>\n  local_day DATE,<br \/>\n  CONSTRAINT fk_dqsite_dom FOREIGN KEY(system_code) REFERENCES dq_domain(code),<br \/>\n  CONSTRAINT fk_dqsite_reg FOREIGN KEY(region_id) REFERENCES dq_region(region_id),<br \/>\n  CONSTRAINT fk_dqsite_cur FOREIGN KEY(cur_code) REFERENCES dq_currency(cur_code)<br \/>\n);<\/p>\n<p>INSERT INTO dq_site (site_id, system_code, region_id, site_name, country, cur_code,<br \/>\n                     amount_usd, amount_orig, created_utc, local_day)<br \/>\nSELECT<br \/>\n  g.n,<br \/>\n  d.code,<br \/>\n  MOD(g.n,12)&#043;1,<br \/>\n  &#039;SITE_&#039;||g.n,<br \/>\n  r.country,<br \/>\n  r.cur_code,<br \/>\n  ROUND(DBMS_RANDOM.VALUE(1000,500000),2),<br \/>\n  ROUND(DBMS_RANDOM.VALUE(1000,500000),2),<br \/>\n  FROM_TZ(CAST(DATE &#039;2026-06-01&#039; &#043; MOD(g.n,30) AS TIMESTAMP),&#039;UTC&#039;),<br \/>\n  TRUNC(CAST(FROM_TZ(CAST(DATE &#039;2026-06-01&#039; &#043; MOD(g.n,30) AS TIMESTAMP),&#039;UTC&#039;)<br \/>\n            AT TIME ZONE r.tz_name AS DATE))<br \/>\nFROM (SELECT LEVEL n FROM dual CONNECT BY LEVEL&lt;&#061;6000) g<br \/>\nJOIN dq_domain d ON d.domain_id &#061; MOD(g.n,8)&#043;1<br \/>\nJOIN dq_region r ON r.region_id &#061; MOD(g.n,12)&#043;1;<\/p>\n<p>CREATE TABLE dq_txn (<br \/>\n  txn_id NUMBER PRIMARY KEY,<br \/>\n  site_id NUMBER,<br \/>\n  system_code VARCHAR2(10),<br \/>\n  region_id NUMBER,<br \/>\n  cur_code VARCHAR2(3),<br \/>\n  amount_orig NUMBER(14,2),<br \/>\n  amount_usd NUMBER(14,2),<br \/>\n  created_utc TIMESTAMP WITH TIME ZONE,<br \/>\n  local_day DATE,<br \/>\n  CONSTRAINT fk_dqtxn_site FOREIGN KEY(site_id) REFERENCES dq_site(site_id),<br \/>\n  CONSTRAINT fk_dqtxn_dom FOREIGN KEY(system_code) REFERENCES dq_domain(code),<br \/>\n  CONSTRAINT fk_dqtxn_reg FOREIGN KEY(region_id) REFERENCES dq_region(region_id)<br \/>\n)<br \/>\nPARTITION BY RANGE (local_day)<br \/>\nINTERVAL (NUMTOYMINTERVAL(1,&#039;MONTH&#039;))<br \/>\n(PARTITION p_init VALUES LESS THAN (DATE &#039;2026-06-01&#039;));<\/p>\n<p>INSERT INTO dq_txn (txn_id, site_id, system_code, region_id, cur_code,<br \/>\n                    amount_orig, amount_usd, created_utc, local_day)<br \/>\nSELECT<br \/>\n  g.n,<br \/>\n  MOD(g.n,6000)&#043;1,<br \/>\n  s.system_code,<br \/>\n  s.region_id,<br \/>\n  s.cur_code,<br \/>\n  ROUND(DBMS_RANDOM.VALUE(10,5000),2),<br \/>\n  ROUND(ROUND(DBMS_RANDOM.VALUE(10,5000),2) * c.rate_to_usd, 2),<br \/>\n  s.created_utc &#043; NUMTODSINTERVAL(MOD(g.n,1440),&#039;MINUTE&#039;),<br \/>\n  s.local_day<br \/>\nFROM (SELECT LEVEL n FROM dual CONNECT BY LEVEL&lt;&#061;12000) g<br \/>\nJOIN dq_site s ON s.site_id &#061; MOD(g.n,6000)&#043;1<br \/>\nJOIN dq_currency c ON c.cur_code &#061; s.cur_code;<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; 4. Indexes (B-tree &#043; composite) &#043; statistics  &#8212; high-concurrency<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\nCREATE INDEX dq_ix_sys_reg ON dq_site(system_code, region_id);<br \/>\nCREATE INDEX dq_ix_site_loc ON dq_site(local_day);<br \/>\nCREATE INDEX dq_ix_txn_day ON dq_txn(local_day);<br \/>\nCREATE INDEX dq_ix_txn_cur ON dq_txn(cur_code);<\/p>\n<p>BEGIN<br \/>\n  DBMS_STATS.GATHER_TABLE_STATS(USER,&#039;DQ_SITE&#039;);<br \/>\n  DBMS_STATS.GATHER_TABLE_STATS(USER,&#039;DQ_TXN&#039;);<br \/>\nEND;<br \/>\n\/<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; 5. Validation helpers &#043; check infrastructure<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<\/p>\n<p>&#8212; Whitelist validator for dynamic identifiers (column names in ORDER BY,<br \/>\n&#8212; dynamic predicates). Rejects anything that is not a real column of dq_site.<br \/>\nCREATE OR REPLACE FUNCTION dq_validate_col(p_col VARCHAR2) RETURN VARCHAR2 IS<br \/>\n  v_ok VARCHAR2(30);<br \/>\nBEGIN<br \/>\n  SELECT column_name INTO v_ok FROM user_tab_columns<br \/>\n   WHERE table_name&#061;&#039;DQ_SITE&#039; AND column_name &#061; UPPER(p_col);<br \/>\n  RETURN v_ok;<br \/>\nEXCEPTION<br \/>\n  WHEN NO_DATA_FOUND THEN<br \/>\n    RAISE_APPLICATION_ERROR(-20001,&#039;Invalid column for dynamic SQL: &#039;||p_col);<br \/>\nEND;<br \/>\n\/<\/p>\n<p>&#8212; Identifier sanitizer (defense-in-depth, mirrors DBMS_ASSERT.SIMPLE_SQL_NAME).<br \/>\n&#8212; Raises if the identifier contains anything outside [A-Za-z0-9_$#] or<br \/>\n&#8212; does not start with a letter.<br \/>\nCREATE OR REPLACE FUNCTION dq_assert_name(p_ident VARCHAR2) RETURN VARCHAR2 IS<br \/>\nBEGIN<br \/>\n  IF p_ident IS NULL OR LENGTH(p_ident)&gt;30 THEN<br \/>\n    RAISE_APPLICATION_ERROR(-20003,&#039;Invalid identifier&#039;);<br \/>\n  END IF;<br \/>\n  IF NOT REGEXP_LIKE(p_ident,&#039;^[A-Za-z][A-Za-z0-9_$#]*$&#039;) THEN<br \/>\n    RAISE_APPLICATION_ERROR(-20003,&#039;Invalid identifier: &#039;||p_ident);<br \/>\n  END IF;<br \/>\n  RETURN p_ident;<br \/>\nEND;<br \/>\n\/<\/p>\n<p>CREATE TABLE dq_val (chk_id VARCHAR2(10), descr VARCHAR2(80), pass CHAR(1), detail VARCHAR2(120));<br \/>\nCREATE OR REPLACE PROCEDURE dq_chk(p_id VARCHAR2, p_desc VARCHAR2, p_pass NUMBER, p_detail VARCHAR2) IS<br \/>\nBEGIN<br \/>\n  INSERT INTO dq_val(chk_id, descr, pass, detail) VALUES (p_id, p_desc, CASE WHEN p_pass&#061;1 THEN &#039;Y&#039; ELSE &#039;N&#039; END, p_detail);<br \/>\nEND;<br \/>\n\/<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; 6. Safe dynamic SQL building blocks<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<\/p>\n<p>&#8212; (A) Parameterized dynamic lookup &#8212; bind variable, immune to injection.<br \/>\nCREATE OR REPLACE FUNCTION dq_param_lookup(p_name VARCHAR2) RETURN NUMBER IS<br \/>\n  v_cnt NUMBER;<br \/>\nBEGIN<br \/>\n  EXECUTE IMMEDIATE &#039;SELECT COUNT(*) FROM dq_site WHERE site_name &#061; :n&#039; INTO v_cnt USING p_name;<br \/>\n  RETURN v_cnt;<br \/>\nEND;<br \/>\n\/<\/p>\n<p>&#8212; (B) DANGEROUS pattern (string concatenation) &#8212; shown ONLY to demonstrate<br \/>\n&#8212;     the vulnerability. Passing &#034;x&#039; OR &#039;1&#039;&#061;&#039;1&#034; makes it return ALL rows.<br \/>\n&#8212;     NEVER use this form with user input.<br \/>\nCREATE OR REPLACE FUNCTION dq_concat_danger(p_name VARCHAR2) RETURN NUMBER IS<br \/>\n  v_cnt NUMBER;<br \/>\nBEGIN<br \/>\n  EXECUTE IMMEDIATE &#039;SELECT COUNT(*) FROM dq_site WHERE site_name &#061; &#039;&#039;&#039;||p_name||&#039;&#039;&#039;&#039; INTO v_cnt;<br \/>\n  RETURN v_cnt;<br \/>\nEND;<br \/>\n\/<\/p>\n<p>&#8212; (C) Runtime filter builder &#8212; native dynamic SQL (EXECUTE IMMEDIATE \/ OPEN&#8230;FOR)<br \/>\n&#8212;     with each optional filter using TWO distinct placeholders (:x_n for the<br \/>\n&#8212;     IS NULL guard, :x_v for the typed compare), bound once each. Dynamic<br \/>\n&#8212;     ORDER BY is whitelist-guarded.<br \/>\nCREATE OR REPLACE FUNCTION dq_count_dynamic(<br \/>\n  p_system_code VARCHAR2 DEFAULT NULL,<br \/>\n  p_region_id   NUMBER   DEFAULT NULL,<br \/>\n  p_min_amount  NUMBER   DEFAULT NULL,<br \/>\n  p_currency    VARCHAR2 DEFAULT NULL<br \/>\n) RETURN NUMBER IS<br \/>\n  v_sql VARCHAR2(2000);<br \/>\n  v_cnt NUMBER;<br \/>\nBEGIN<br \/>\n  &#8212; Native dynamic SQL (DBMS_SQL is denied here via ORA-29471). Each optional<br \/>\n  &#8212; filter uses TWO distinct placeholders: :x_n for the (IS NULL) guard and :x_v<br \/>\n  &#8212; for the typed comparison. EXECUTE IMMEDIATE binds by POSITION, so the USING<br \/>\n  &#8212; list must hold one value per placeholder occurrence (8 here). Reusing one name<br \/>\n  &#8212; for both the untyped IS NULL and the typed compare raises ORA-00932.<br \/>\n  v_sql :&#061; &#039;SELECT COUNT(*) FROM dq_site&#039;<br \/>\n    ||&#039; WHERE (:sc_n IS NULL OR system_code &#061; :sc_v)&#039;<br \/>\n    ||&#039;   AND (:rg_n IS NULL OR region_id &#061; :rg_v)&#039;<br \/>\n    ||&#039;   AND (:am_n IS NULL OR amount_usd &gt;&#061; :am_v)&#039;<br \/>\n    ||&#039;   AND (:cu_n IS NULL OR cur_code &#061; :cu_v)&#039;;<br \/>\n  EXECUTE IMMEDIATE v_sql INTO v_cnt<br \/>\n    USING p_system_code, p_system_code, p_region_id, p_region_id, p_min_amount, p_min_amount, p_currency, p_currency;<br \/>\n  RETURN NVL(v_cnt,0);<br \/>\nEND;<br \/>\n\/<\/p>\n<p>&#8212; (D) Refcursor variant of the runtime filter (for UIs \/ reports).<br \/>\nCREATE OR REPLACE PROCEDURE dq_search_dynamic(<br \/>\n  p_system_code VARCHAR2 DEFAULT NULL,<br \/>\n  p_region_id   NUMBER   DEFAULT NULL,<br \/>\n  p_min_amount  NUMBER   DEFAULT NULL,<br \/>\n  p_currency    VARCHAR2 DEFAULT NULL,<br \/>\n  p_order_col   VARCHAR2 DEFAULT &#039;site_id&#039;,<br \/>\n  p_rc          OUT SYS_REFCURSOR<br \/>\n) IS<br \/>\n  v_sql VARCHAR2(4000);<br \/>\n  v_order VARCHAR2(30) :&#061; dq_validate_col(p_order_col); &#8212; whitelist<br \/>\nBEGIN<br \/>\n  v_sql :&#061; &#039;SELECT site_id, system_code, region_id, site_name, cur_code, amount_usd FROM dq_site&#039;<br \/>\n    ||&#039; WHERE (:sc_n IS NULL OR system_code &#061; :sc_v)&#039;<br \/>\n    ||&#039;   AND (:rg_n IS NULL OR region_id &#061; :rg_v)&#039;<br \/>\n    ||&#039;   AND (:am_n IS NULL OR amount_usd &gt;&#061; :am_v)&#039;<br \/>\n    ||&#039;   AND (:cu_n IS NULL OR cur_code &#061; :cu_v)&#039;<br \/>\n    ||&#039; ORDER BY &#039;||v_order;<br \/>\n  &#8212; OPEN&#8230;FOR USING cannot infer bind types from an ALL-NULL list (ORA-00932);<br \/>\n  &#8212; when no filter is supplied, open without binds.<br \/>\n  IF p_system_code IS NULL AND p_region_id IS NULL AND p_min_amount IS NULL AND p_currency IS NULL THEN<br \/>\n    OPEN p_rc FOR v_sql;<br \/>\n  ELSE<br \/>\n    OPEN p_rc FOR v_sql<br \/>\n      USING p_system_code, p_system_code, p_region_id, p_region_id, p_min_amount, p_min_amount, p_currency, p_currency;<br \/>\n  END IF;<br \/>\nEND;<br \/>\n\/<\/p>\n<p>&#8212; (E) AUTHID CURRENT_USER package &#8212; dynamic SQL runs with the INVOKER&#039;s<br \/>\n&#8212;     privileges (security best practice for multi-tenant mid-platforms).<br \/>\n&#8212;     Includes a RESULT_CACHE &#043; PARALLEL function for trillion-scale rollups.<br \/>\nCREATE OR REPLACE PACKAGE dq_pkg AUTHID CURRENT_USER IS<br \/>\n  FUNCTION region_sales(p_region NUMBER) RETURN NUMBER RESULT_CACHE;<br \/>\n  FUNCTION dynamic_filter(p_col VARCHAR2, p_val VARCHAR2) RETURN NUMBER;<br \/>\nEND dq_pkg;<br \/>\n\/<br \/>\nCREATE OR REPLACE PACKAGE BODY dq_pkg IS<br \/>\n  FUNCTION region_sales(p_region NUMBER) RETURN NUMBER RESULT_CACHE IS<br \/>\n    v NUMBER;<br \/>\n  BEGIN<br \/>\n    EXECUTE IMMEDIATE &#039;SELECT \/*&#043; PARALLEL(4) *\/ SUM(amount_usd) FROM dq_txn WHERE region_id &#061; :r&#039;<br \/>\n      INTO v USING p_region;<br \/>\n    RETURN NVL(v,0);<br \/>\n  END;<br \/>\n  FUNCTION dynamic_filter(p_col VARCHAR2, p_val VARCHAR2) RETURN NUMBER IS<br \/>\n    v_cnt NUMBER;<br \/>\n    v_col VARCHAR2(30) :&#061; dq_validate_col(p_col); &#8212; whitelist guard<br \/>\n  BEGIN<br \/>\n    EXECUTE IMMEDIATE &#039;SELECT COUNT(*) FROM dq_site WHERE &#039;||v_col||&#039; &#061; :v&#039; INTO v_cnt USING p_val;<br \/>\n    RETURN v_cnt;<br \/>\n  END;<br \/>\nEND dq_pkg;<br \/>\n\/<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; 7. Demos : dynamic query building, security, best practices<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<\/p>\n<p>PROMPT &#8212; A. Sample sites (geography\/domain mix)<br \/>\nSELECT site_id, system_code, region_id, site_name, cur_code, amount_usd<br \/>\nFROM dq_site WHERE ROWNUM&lt;&#061;5;<\/p>\n<p>PROMPT &#8212; B. Parameterized dynamic lookup (bind variable &#061;&gt; safe)<br \/>\nSELECT dq_param_lookup(&#039;SITE_1&#039;) exact_match FROM dual;<\/p>\n<p>PROMPT &#8212; C. Runtime filter: ERP sites in region 1, min amount 100000<br \/>\nSELECT dq_count_dynamic(p_system_code&#061;&gt;&#039;ERP&#039;, p_region_id&#061;&gt;1, p_min_amount&#061;&gt;100000) erp_r1_cnt FROM dual;<\/p>\n<p>PROMPT &#8212; D. DBMS_SQL dynamic filter: CRM sites only<br \/>\nSELECT dq_count_dynamic(p_system_code&#061;&gt;&#039;CRM&#039;) crm_cnt FROM dual;<\/p>\n<p>PROMPT &#8212; E. Whitelist-guarded dynamic ORDER BY (top 5 by amount_usd), region 1<br \/>\nDECLARE<br \/>\n  rc SYS_REFCURSOR;<br \/>\n  v_id dq_site.site_id%TYPE; v_sys dq_site.system_code%TYPE; v_reg dq_site.region_id%TYPE;<br \/>\n  v_name dq_site.site_name%TYPE; v_cur dq_site.cur_code%TYPE; v_amt dq_site.amount_usd%TYPE;<br \/>\nBEGIN<br \/>\n  dq_search_dynamic(p_order_col&#061;&gt;&#039;amount_usd&#039;, p_region_id&#061;&gt;1, p_rc&#061;&gt;rc);<br \/>\n  LOOP<br \/>\n    FETCH rc INTO v_id, v_sys, v_reg, v_name, v_cur, v_amt;<br \/>\n    EXIT WHEN rc%NOTFOUND OR rc%ROWCOUNT&gt;5;<br \/>\n    DBMS_OUTPUT.PUT_LINE(&#039;site&#061;&#039;||v_id||&#039; sys&#061;&#039;||v_sys||&#039; usd&#061;&#039;||v_amt);<br \/>\n  END LOOP;<br \/>\n  CLOSE rc;<br \/>\nEND;<br \/>\n\/<\/p>\n<p>PROMPT &#8212; F. SQL injection: safe (bind) vs DANGEROUS (concat). DO NOT USE concat.<br \/>\nDECLARE<br \/>\n  v_safe NUMBER; v_danger NUMBER;<br \/>\n  inj VARCHAR2(50) :&#061; &#039;x&#039;&#039; OR &#039;&#039;1&#039;&#039;&#061;&#039;&#039;1&#039;;<br \/>\nBEGIN<br \/>\n  v_safe   :&#061; dq_param_lookup(inj);   &#8212; bind &#061;&gt; literal match &#061;&gt; 0<br \/>\n  v_danger :&#061; dq_concat_danger(inj);  &#8212; concat &#061;&gt; predicate hijack &#061;&gt; all rows<br \/>\n  DBMS_OUTPUT.PUT_LINE(&#039;SAFE(bind) rows   &#061; &#039;||v_safe||&#039;   (injection neutralized, expected 0)&#039;);<br \/>\n  DBMS_OUTPUT.PUT_LINE(&#039;DANGER(concat) row&#061; &#039;||v_danger||&#039;   (LEAK: returns every row!)&#039;);<br \/>\nEND;<br \/>\n\/<\/p>\n<p>PROMPT &#8212; G. Identifier validation: DBMS_ASSERT-style guard rejects a malicious identifier<br \/>\nDECLARE<br \/>\n  v VARCHAR2(30);<br \/>\nBEGIN<br \/>\n  BEGIN<br \/>\n    v :&#061; dq_assert_name(&#039;site_id; DROP TABLE dq_site&#8211;&#039;);<br \/>\n    DBMS_OUTPUT.PUT_LINE(&#039;UNEXPECTED: accepted malicious identifier&#039;);<br \/>\n  EXCEPTION<br \/>\n    WHEN OTHERS THEN<br \/>\n      DBMS_OUTPUT.PUT_LINE(&#039;REJECTED malicious identifier (good): &#039;||SQLERRM);<br \/>\n  END;<br \/>\n  v :&#061; dq_assert_name(&#039;site_id&#039;);<br \/>\n  DBMS_OUTPUT.PUT_LINE(&#039;Accepted valid identifier: &#039;||v);<br \/>\nEND;<br \/>\n\/<\/p>\n<p>PROMPT &#8212; H. AUTHID CURRENT_USER package: whitelist dynamic column filter<br \/>\nSELECT dq_pkg.dynamic_filter(&#039;system_code&#039;,&#039;WMS&#039;) wms_cnt FROM dual;<br \/>\nSELECT ROUND(dq_pkg.region_sales(5),2) cny_region_sales_usd FROM dual;<\/p>\n<p>PROMPT &#8212; I. EXPLAIN PLAN for a single-day dynamic query (partition pruning)<br \/>\nDECLARE<br \/>\n  v_sql VARCHAR2(4000);<br \/>\nBEGIN<br \/>\n  BEGIN DELETE FROM plan_table WHERE statement_id&#061;&#039;dq_p&#039;; END;<br \/>\n  v_sql :&#061; &#039;SELECT \/*&#043; FULL(t) *\/ COUNT(*) FROM dq_txn t WHERE local_day &#061; DATE &#039;&#039;2026-06-15&#039;&#039; AND system_code&#061;&#039;&#039;ERP&#039;&#039;&#039;;<br \/>\n  EXECUTE IMMEDIATE &#039;EXPLAIN PLAN SET STATEMENT_ID&#061;&#039;&#039;dq_p&#039;&#039; FOR &#039;||v_sql;<br \/>\n  FOR r IN (SELECT LPAD(&#039; &#039;,2*(LEVEL-1))||operation||&#039; &#039;||options||&#039; &#039;||object_name plan_line<br \/>\n              FROM plan_table<br \/>\n             START WITH id&#061;0 AND statement_id&#061;&#039;dq_p&#039;<br \/>\n             CONNECT BY PRIOR id &#061; parent_id AND statement_id&#061;&#039;dq_p&#039;) LOOP<br \/>\n    DBMS_OUTPUT.PUT_LINE(r.plan_line);<br \/>\n  END LOOP;<br \/>\nEND;<br \/>\n\/<\/p>\n<p>PROMPT &#8212; J. International timezone: rows whose LOCAL day differs from UTC day<br \/>\nSELECT COUNT(*) rows_shifted_to_local_day<br \/>\nFROM dq_site WHERE local_day &lt;&gt; TRUNC(CAST(created_utc AS DATE));<\/p>\n<p>PROMPT &#8212; K. Multi-currency report: only SUM(amount_usd) is comparable across currencies<br \/>\nSELECT cur_code, COUNT(*) txns, ROUND(SUM(amount_usd),2) usd_total<br \/>\nFROM dq_txn GROUP BY cur_code ORDER BY cur_code;<\/p>\n<p>PROMPT &#8212; L. RESULT_CACHE &#043; PARALLEL rollup matches static sum (trillion-scale pattern)<br \/>\nSELECT ROUND(dq_pkg.region_sales(3),2) hkg_region_usd,<br \/>\n       (SELECT ROUND(SUM(amount_usd),2) FROM dq_txn WHERE region_id&#061;3) static_usd<br \/>\nFROM dual;<\/p>\n<p>PROMPT &#8212; M. All-NULL runtime filters &#061;&gt; full set returned<br \/>\nSELECT dq_count_dynamic() full_set FROM dual;<\/p>\n<p>PROMPT &#8212; N. Domain (OA\/ERP\/CRM\/HRM\/MES\/SCM\/WMS\/KMS) distribution across 6000 sites<br \/>\nSELECT system_code, COUNT(*) cnt FROM dq_site GROUP BY system_code ORDER BY system_code;<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; 8. Self-checks V1..V17<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\nDECLARE<br \/>\n  v1 NUMBER; v2 NUMBER; v3 NUMBER; v4 NUMBER; v5 NUMBER; v6 NUMBER;<br \/>\n  v7 NUMBER; v8ok NUMBER:&#061;0; v9ok NUMBER:&#061;0; v10 VARCHAR2(30); v11 NUMBER;<br \/>\n  v12 NUMBER; v13a NUMBER; v13b NUMBER; v13g NUMBER; v14 NUMBER; v15 NUMBER;<br \/>\n  v16pkg NUMBER; v16static NUMBER; v17 NUMBER;<br \/>\n  v_inj VARCHAR2(50) :&#061; &#039;x&#039;&#039; OR &#039;&#039;1&#039;&#039;&#061;&#039;&#039;1&#039;;<br \/>\n  v_erp NUMBER; v_crm NUMBER;<br \/>\nBEGIN<br \/>\n  &#8212; V1 row count<br \/>\n  SELECT COUNT(*) INTO v1 FROM dq_site;<br \/>\n  dq_chk(&#039;V1&#039;,&#039;dq_site row count &#061; 6000&#039;, CASE WHEN v1&#061;6000 THEN 1 ELSE 0 END, &#039;rows&#061;&#039;||v1);<br \/>\n  &#8212; V2 domains<br \/>\n  SELECT COUNT(*) INTO v2 FROM dq_domain;<br \/>\n  dq_chk(&#039;V2&#039;,&#039;8 domains (OA..KMS)&#039;, CASE WHEN v2&#061;8 THEN 1 ELSE 0 END, &#039;domains&#061;&#039;||v2);<br \/>\n  &#8212; V3 txn rows<br \/>\n  SELECT COUNT(*) INTO v3 FROM dq_txn;<br \/>\n  dq_chk(&#039;V3&#039;,&#039;dq_txn row count &#061; 12000&#039;, CASE WHEN v3&#061;12000 THEN 1 ELSE 0 END, &#039;rows&#061;&#039;||v3);<br \/>\n  &#8212; V4 parameterized lookup (by site_name) matches static count<br \/>\n  SELECT COUNT(*) INTO v_erp FROM dq_site WHERE site_name&#061;&#039;SITE_1&#039;;<br \/>\n  v4 :&#061; dq_param_lookup(&#039;SITE_1&#039;);<br \/>\n  dq_chk(&#039;V4&#039;,&#039;param lookup by name &#061; static&#039;, CASE WHEN v4&#061;v_erp THEN 1 ELSE 0 END, &#039;dyn&#061;&#039;||v4||&#039; stat&#061;&#039;||v_erp);<br \/>\n  &#8212; V5 dynamic filter region&#061;1<br \/>\n  SELECT COUNT(*) INTO v5 FROM dq_site WHERE region_id&#061;1;<br \/>\n  dq_chk(&#039;V5&#039;,&#039;dyn filter region&#061;1 matches&#039;, CASE WHEN dq_count_dynamic(p_region_id&#061;&gt;1)&#061;v5 THEN 1 ELSE 0 END, &#039;cnt&#061;&#039;||v5);<br \/>\n  &#8212; V6 dynamic filter CRM<br \/>\n  SELECT COUNT(*) INTO v_crm FROM dq_site WHERE system_code&#061;&#039;CRM&#039;;<br \/>\n  dq_chk(&#039;V6&#039;,&#039;dyn filter CRM matches&#039;, CASE WHEN dq_count_dynamic(p_system_code&#061;&gt;&#039;CRM&#039;)&#061;v_crm THEN 1 ELSE 0 END, &#039;cnt&#061;&#039;||v_crm);<br \/>\n  &#8212; V7 injection neutralized by bind<br \/>\n  v7 :&#061; dq_param_lookup(v_inj);<br \/>\n  dq_chk(&#039;V7&#039;,&#039;bind neutralizes injection (&#061;0)&#039;, CASE WHEN v7&#061;0 THEN 1 ELSE 0 END, &#039;cnt&#061;&#039;||v7);<br \/>\n  &#8212; V8 assert rejects malicious identifier<br \/>\n  BEGIN<br \/>\n    v10 :&#061; dq_assert_name(&#039;site_id; DROP TABLE dq_site&#8211;&#039;);<br \/>\n  EXCEPTION<br \/>\n    WHEN OTHERS THEN v8ok :&#061; 1;<br \/>\n  END;<br \/>\n  dq_chk(&#039;V8&#039;,&#039;assert rejects malicious ident&#039;, v8ok, &#039;ok&#061;&#039;||v8ok);<br \/>\n  &#8212; V9 whitelist rejects invalid column<br \/>\n  BEGIN<br \/>\n    v10 :&#061; dq_validate_col(&#039;not_a_column&#039;);<br \/>\n  EXCEPTION<br \/>\n    WHEN OTHERS THEN v9ok :&#061; 1;<br \/>\n  END;<br \/>\n  dq_chk(&#039;V9&#039;,&#039;whitelist rejects bad column&#039;, v9ok, &#039;ok&#061;&#039;||v9ok);<br \/>\n  &#8212; V10 whitelist accepts valid column<br \/>\n  v10 :&#061; dq_validate_col(&#039;site_name&#039;);<br \/>\n  dq_chk(&#039;V10&#039;,&#039;whitelist accepts valid column&#039;, CASE WHEN v10&#061;&#039;SITE_NAME&#039; THEN 1 ELSE 0 END, &#039;col&#061;&#039;||v10);<br \/>\n  &#8212; V11 dynamic ORDER BY returns smallest site_id first<br \/>\n  SELECT site_id INTO v11 FROM (SELECT site_id FROM dq_site ORDER BY site_id) WHERE ROWNUM&#061;1;<br \/>\n  dq_chk(&#039;V11&#039;,&#039;whitelist ORDER BY works&#039;, CASE WHEN v11&#061;1 THEN 1 ELSE 0 END, &#039;min_id&#061;&#039;||v11);<br \/>\n  &#8212; V12 timezone shift exists<br \/>\n  SELECT COUNT(*) INTO v12 FROM dq_site WHERE local_day &lt;&gt; TRUNC(CAST(created_utc AS DATE));<br \/>\n  dq_chk(&#039;V12&#039;,&#039;timezone local_day shifts exist&#039;, CASE WHEN v12&gt;0 THEN 1 ELSE 0 END, &#039;shifted&#061;&#039;||v12);<br \/>\n  &#8212; V13 multi-currency normalization<br \/>\n  SELECT COUNT(*) INTO v13g FROM dq_txn;<br \/>\n  SELECT ROUND(SUM(amount_usd),2), ROUND(SUM(amount_orig),2) INTO v13a, v13b FROM dq_txn;<br \/>\n  dq_chk(&#039;V13&#039;,&#039;multi-cur: usd vs orig differ but sum&gt;0&#039;,<br \/>\n         CASE WHEN v13a&gt;0 AND v13b&gt;0 AND ABS(v13a-v13b)&gt;1 THEN 1 ELSE 0 END,<br \/>\n         &#039;usd&#061;&#039;||v13a||&#039; orig&#061;&#039;||v13b||&#039; g&#061;&#039;||v13g);<br \/>\n  &#8212; V14 stats gathered<br \/>\n  SELECT num_rows INTO v14 FROM user_tables WHERE table_name&#061;&#039;DQ_SITE&#039;;<br \/>\n  dq_chk(&#039;V14&#039;,&#039;stats num_rows &gt; 0&#039;, CASE WHEN v14&gt;0 THEN 1 ELSE 0 END, &#039;num_rows&#061;&#039;||v14);<br \/>\n  &#8212; V15 all-NULL filter &#061;&gt; full set<br \/>\n  v15 :&#061; dq_count_dynamic();<br \/>\n  dq_chk(&#039;V15&#039;,&#039;all-NULL filter &#061; full set&#039;, CASE WHEN v15&#061;6000 THEN 1 ELSE 0 END, &#039;cnt&#061;&#039;||v15);<br \/>\n  &#8212; V16 AUTHID package result_cache matches static<br \/>\n  SELECT ROUND(SUM(amount_usd),2) INTO v16static FROM dq_txn WHERE region_id&#061;1;<br \/>\n  v16pkg :&#061; ROUND(dq_pkg.region_sales(1),2);<br \/>\n  dq_chk(&#039;V16&#039;,&#039;AUTHID pkg RESULT_CACHE matches&#039;, CASE WHEN v16pkg&#061;v16static THEN 1 ELSE 0 END, &#039;pkg&#061;&#039;||v16pkg||&#039; stat&#061;&#039;||v16static);<br \/>\n  &#8212; V17 partition pruning present in single-day plan<br \/>\n  BEGIN DELETE FROM plan_table WHERE statement_id&#061;&#039;dq_p&#039;; END;<br \/>\n  EXECUTE IMMEDIATE &#039;EXPLAIN PLAN SET STATEMENT_ID&#061;&#039;&#039;dq_p&#039;&#039; FOR SELECT \/*&#043; FULL(t) *\/ COUNT(*) FROM dq_txn t WHERE local_day &#061; DATE &#039;&#039;2026-06-15&#039;&#039; AND system_code&#061;&#039;&#039;ERP&#039;&#039;&#039;;<br \/>\n  SELECT COUNT(*) INTO v17 FROM plan_table WHERE statement_id&#061;&#039;dq_p&#039; AND operation LIKE &#039;%PARTITION%&#039;;<br \/>\n  dq_chk(&#039;V17&#039;,&#039;partition pruning in plan&#039;, CASE WHEN v17&gt;0 THEN 1 ELSE 0 END, &#039;part_ops&#061;&#039;||v17);<br \/>\nEND;<br \/>\n\/<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; Q. Self-check summary<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\nSET PAGES 100 LINES 200<br \/>\nSELECT chk_id, descr, pass, detail FROM dq_val ORDER BY chk_id;<br \/>\nSELECT &#039;CHECK SUMMARY: &#039;||SUM(CASE WHEN pass&#061;&#039;Y&#039; THEN 1 ELSE 0 END)||&#039;\/&#039;||COUNT(*)||&#039; PASS&#039; AS result<br \/>\nFROM dq_val;<\/p>\n<p>&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\n&#8212; R. Conclusions (12, ASCII) &#8212; Dynamic Query Building best practices<br \/>\n&#8212; &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<br \/>\nPROMPT 1) ALWAYS parameterize dynamic SQL with bind variables (the USING clause of EXECUTE IMMEDIATE \/ OPEN&#8230;FOR). This is the single most important SQL-injection control. NOTE: DBMS_SQL can be denied (ORA-29471) in locked-down instances &#8212; native dynamic SQL is always available.<br \/>\nPROMPT 2) Never concatenate user input into SQL text. The dq_concat_danger demo leaks ALL rows on &#034;x&#039; OR &#039;1&#039;&#061;&#039;1&#034; &#8212; do not ship that pattern.<br \/>\nPROMPT 3) For dynamic identifiers (column names, table names, ORDER BY), use a WHITELIST (validate against user_tab_columns) &#8212; never a blacklist.<br \/>\nPROMPT 4) DBMS_ASSERT (SIMPLE_SQL_NAME \/ QUALIFIED_SQL_NAME \/ ENQUOTE_LITERAL) is the built-in sanitizer; a manual regex guard also works if it is rejected by default.<br \/>\nPROMPT 5) For conditional runtime filters with native dynamic SQL, give each optional filter TWO distinct placeholders &#8212; :x_n for the (IS NULL) guard and :x_v for the typed compare &#8212; and bind each value once per occurrence. Never reuse one name for both the untyped IS NULL and the typed compare (ORA-00932); EXECUTE IMMEDIATE binds by position, so supply one value per placeholder occurrence.<br \/>\nPROMPT 6) Use AUTHID CURRENT_USER for packages that build dynamic SQL in multi-tenant platforms so they run with the invoker&#039;s privileges (least privilege).<br \/>\nPROMPT 7) RESULT_CACHE &#043; PARALLEL hints turn repeatable rollups into trillion-scale, low-latency queries; pair with current statistics.<br \/>\nPROMPT 8) Gather statistics (DBMS_STATS) so the optimizer picks the right plan for dynamically built predicates.<br \/>\nPROMPT 9) INTERVAL\/RANGE partitioning on local_day enables partition pruning; EXPLAIN PLAN shows the PARTITION RANGE operation.<br \/>\nPROMPT 10) Store UTC (TIMESTAMP WITH TIME ZONE) and derive local_day with AT TIME ZONE so global reports respect each region&#039;s calendar day.<br \/>\nPROMPT 11) Normalize multi-currency with SUM(amount_usd); never SUM(amount_orig) across different currencies &#8212; amounts are not additive.<br \/>\nPROMPT 12) Oracle unquoted identifiers must start with a letter; &#039;_name&#039; &#061;&gt; ORA-00911. Prefix dynamic objects with DQ_. Add EXIT so SQL*Plus terminates cleanly.<\/p>\n<p>EXIT<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\/* MD \/ \u5bcc\u6587\u672c\u4e2d\u7684 .toc\uff08\u542b\u535a\u5ba2\u56ed\u642c\u5bb6\u7b49\u5d4c\u5957\u7ed3\u6784\uff09\uff1b.toc-box \u5728\u4fa7\u680f\uff0c\u4e0d\u53d7\u5f71\u54cd *\/#content_views .toc,\/* \u7f16\u8f91\u5668\u5e38\u5728\u76ee\u5f55\u524d\u540e\u63d2\u5165\u7a7a p\uff08:empty \u4ecd\u5360 20px\uff09\uff0c\u4e00\u5e76\u53bb\u6389\u907f\u514d\u9876\u7a7a\u9699 *\/#content_views.markdown_views &gt; p:empty:has(+ .toc),#content_views.markdown_views &gt; .toc + p:empty,\/* \u5bcc\u6587\u672c\u65e7\u7248\u76ee\u5f55\u6807\u8bb0 *\/#content<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[604,768,323,2330,100],"topic":[],"class_list":["post-122531","post","type-post","status-publish","format-standard","hentry","category-server","tag-oracle","tag-sql","tag-323","tag-2330","tag-100"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>sql: Designing Efficient SQL SELECT Queries using Oracel 21c - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/122531.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"sql: Designing Efficient SQL SELECT Queries using Oracel 21c - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\/* MD \/ \u5bcc\u6587\u672c\u4e2d\u7684 .toc\uff08\u542b\u535a\u5ba2\u56ed\u642c\u5bb6\u7b49\u5d4c\u5957\u7ed3\u6784\uff09\uff1b.toc-box \u5728\u4fa7\u680f\uff0c\u4e0d\u53d7\u5f71\u54cd *\/#content_views .toc,\/* \u7f16\u8f91\u5668\u5e38\u5728\u76ee\u5f55\u524d\u540e\u63d2\u5165\u7a7a p\uff08:empty \u4ecd\u5360 20px\uff09\uff0c\u4e00\u5e76\u53bb\u6389\u907f\u514d\u9876\u7a7a\u9699 *\/#content_views.markdown_views &gt; p:empty:has(+ .toc),#content_views.markdown_views &gt; .toc + p:empty,\/* \u5bcc\u6587\u672c\u65e7\u7248\u76ee\u5f55\u6807\u8bb0 *\/#content\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/122531.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-11-04T19:08:39+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/122531.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/122531.html\",\"name\":\"sql: Designing Efficient SQL SELECT Queries using Oracel 21c - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-11-04T19:08:39+00:00\",\"dateModified\":\"2026-11-04T19:08:39+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/122531.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/122531.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/122531.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"sql: Designing Efficient SQL SELECT Queries using Oracel 21c\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"sql: Designing Efficient SQL SELECT Queries using Oracel 21c - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/122531.html","og_locale":"zh_CN","og_type":"article","og_title":"sql: Designing Efficient SQL SELECT Queries using Oracel 21c - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\/* MD \/ \u5bcc\u6587\u672c\u4e2d\u7684 .toc\uff08\u542b\u535a\u5ba2\u56ed\u642c\u5bb6\u7b49\u5d4c\u5957\u7ed3\u6784\uff09\uff1b.toc-box \u5728\u4fa7\u680f\uff0c\u4e0d\u53d7\u5f71\u54cd *\/#content_views .toc,\/* \u7f16\u8f91\u5668\u5e38\u5728\u76ee\u5f55\u524d\u540e\u63d2\u5165\u7a7a p\uff08:empty \u4ecd\u5360 20px\uff09\uff0c\u4e00\u5e76\u53bb\u6389\u907f\u514d\u9876\u7a7a\u9699 *\/#content_views.markdown_views &gt; p:empty:has(+ .toc),#content_views.markdown_views &gt; .toc + p:empty,\/* \u5bcc\u6587\u672c\u65e7\u7248\u76ee\u5f55\u6807\u8bb0 *\/#content","og_url":"https:\/\/www.wsisp.com\/helps\/122531.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-11-04T19:08:39+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"20 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/122531.html","url":"https:\/\/www.wsisp.com\/helps\/122531.html","name":"sql: Designing Efficient SQL SELECT Queries using Oracel 21c - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-11-04T19:08:39+00:00","dateModified":"2026-11-04T19:08:39+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/122531.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/122531.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/122531.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"sql: Designing Efficient SQL SELECT Queries using Oracel 21c"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/122531","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=122531"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/122531\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=122531"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=122531"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=122531"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=122531"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}