Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用复合键的查询中的\u在哪里?_Sql_Oracle - Fatal编程技术网

Sql 使用复合键的查询中的\u在哪里?

Sql 使用复合键的查询中的\u在哪里?,sql,oracle,Sql,Oracle,假设我有一个包含两部分复合键的表和4条记录,如下所示: KEY_PART_1 KEY_PART_2 A 1 B 1 C 2 C 3 我想编写一些动态SQL,使用“WHERE IN”子句仅选择记录B、1和C、2,而不选择a、1或C、3 在没有临时表的情况下,有什么方法可以做到这一点吗 这并不重要,但我们目前正在使用Oracle,并希望很快转向PostgreSQL。此语法适用于Oracle和PostgreSQL: SELECT

假设我有一个包含两部分复合键的表和4条记录,如下所示:

KEY_PART_1 KEY_PART_2
A          1
B          1
C          2
C          3
我想编写一些动态SQL,使用“WHERE IN”子句仅选择记录B、1和C、2,而不选择a、1或C、3

在没有临时表的情况下,有什么方法可以做到这一点吗


这并不重要,但我们目前正在使用Oracle,并希望很快转向PostgreSQL。

此语法适用于Oracle和PostgreSQL:

SELECT *
  FROM table_name
 WHERE (key_part_1, key_part_2) IN ( ('B',1), ('C',2) );

我不确定,但我认为您希望这样的产品适用于几乎所有的RDBMS:

select KEY_PART_1, KEY_PART_2 from your_table where KEY_PART_1='B' and KEY_PART_2 = '1'
UNION
select KEY_PART_1, KEY_PART_2 from your_table where KEY_PART_1='C' and KEY_PART_2 = '2'

根据@Justin Cave的回答,下面是一个小测试用例,它表明Oracle将对以下过滤器谓词执行索引范围扫描,然后执行INLIST迭代器

WHERE (key_part_1, key_part_2) IN ( ('B',1), ('C',2) )
SQL> CREATE INDEX t_idx ON t(key1, key2);

Index created.

SQL>
设置

SQL> CREATE TABLE t(key1 VARCHAR2(1), key2 NUMBER);

Table created.

SQL>
SQL> INSERT INTO t VALUES('A', 1);

1 row created.

SQL> INSERT INTO t VALUES('B', 1);

1 row created.

SQL> INSERT INTO t VALUES('C', 2);

1 row created.

SQL> INSERT INTO t VALUES('C', 3);

1 row created.

SQL>
SQL> COMMIT;

Commit complete.

SQL>
关于键1和键2的综合指数

WHERE (key_part_1, key_part_2) IN ( ('B',1), ('C',2) )
SQL> CREATE INDEX t_idx ON t(key1, key2);

Index created.

SQL>
收集统计信息:

SQL> EXEC DBMS_STATS.gather_table_stats('LALIT', 'T');

PL/SQL procedure successfully completed.

SQL>
SQL> SELECT * FROM t
  2  WHERE (key1, key2) IN ( ('B',1), ('C',2) );

K       KEY2
- ----------
B          1
C          2

SQL>
执行查询:

SQL> EXEC DBMS_STATS.gather_table_stats('LALIT', 'T');

PL/SQL procedure successfully completed.

SQL>
SQL> SELECT * FROM t
  2  WHERE (key1, key2) IN ( ('B',1), ('C',2) );

K       KEY2
- ----------
B          1
C          2

SQL>
因此,它给出了正确的输出

让我们看看解释计划

WHERE (key_part_1, key_part_2) IN ( ('B',1), ('C',2) )
SQL> CREATE INDEX t_idx ON t(key1, key2);

Index created.

SQL>
大小写#1索引顺序相同的键值对。领先关键在领先

SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2301620486

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |     2 |    10 |     1   (0)| 00:00:01 |
|   1 |  INLIST ITERATOR  |       |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| T_IDX |     2 |    10 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   2 - access(("KEY1"='B' AND "KEY2"=1 OR "KEY1"='C' AND "KEY2"=2))

14 rows selected.
大小写#2索引的相反顺序的键值对。反向引导键

SQL> EXPLAIN PLAN FOR SELECT * FROM t
  2  WHERE (key2, key1) IN ( (1, 'B'), (2, 'C') );

Explained.

SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2301620486

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |     2 |    10 |     1   (0)| 00:00:01 |
|   1 |  INLIST ITERATOR  |       |       |       |            |          |
|*  2 |   INDEX RANGE SCAN| T_IDX |     2 |    10 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------

   2 - access(("KEY1"='B' AND "KEY2"=1 OR "KEY1"='C' AND "KEY2"=2))

14 rows selected.

在这两种情况下,Oracle使用索引

不知道Oracle是否存在相同的问题,但是在MySQL中,如果您使用这种语法,它将不会使用索引。您知道如何在SQL查询中使用ODP.NET?@Barmar这样做吗?它会确切地影响是否依赖复合索引。@Kamafeather只有当
WHERE
子句使用键中的列的子集时,这才相关,但此查询使用整个密钥。但是当我测试它时,MySQL仍然没有使用这个键,只是一个注释,尽管这个查询会给出所需的输出。但是,此查询将进行2次索引范围扫描。Justin的查询将执行单个索引范围扫描。因此,就性能而言,Justin的查询更好。