我有一个数据库,其中字符集定义为UTF8。一个带有varchar(60)字段的表VSL_STATIC_DATA,该字段名为VESSEL_NAME,具有UNICODE_CI_AI排序规则,该字段上有一个升序索引。另一个名为TABLE_PORTS的表,其字段PORT_ID为主键,即VSL_STATIC_DATA表中的FK(PORT_OF_REG_ID)
当我运行以下查询时,它使用索引按名称搜索容器,然后使用索引链接到注册表端口:
SELECT FIRST (5) SKIP (0)
VSL.VESSEL_ID,
VSL.UPDATE_TIME,
VSL.VESSEL_NAME,
VSL.CALL_SIGN,
VSL.MMSI,
VSL.IMO_NUM,
VSL.LOA,
VSL.WIDTH,
VSL.NRT,
VSL.GRT,
VSL.DWT,
PORT.PORT_ID,
PORT.PORT_NAME
FROM
VSL_STATIC_DATA VSL
LEFT JOIN
TABLE_PORTS PORT
ON VSL.PORT_OF_REG_ID = PORT.PORT_ID
WHERE VSL.VESSEL_NAME LIKE 'TE%'
但是,如果现在我将完全相同的查询放在存储过程中:
CREATE PROCEDURE FIND_VESSEL_BY_NAME(
VSL_NAME VARCHAR(60),
FIRST_N INTEGER,
SKIP_N INTEGER)
RETURNS(
VESSEL_ID BIGINT,
UPDATE_TIME BIGINT,
VESSEL_NAME VARCHAR(60),
CALL_SIGN VARCHAR(10),
MMSI BIGINT,
IMO INTEGER,
LOA SMALLINT,
WIDTH SMALLINT,
NRT INTEGER,
GRT INTEGER,
DWT INTEGER,
PORT_OF_REG_ID BIGINT,
PORT_OF_REG VARCHAR(75))
AS
BEGIN
/* Procedure body */
FOR
SELECT FIRST (:FIRST_N) SKIP (:SKIP_N)
VSL.VESSEL_ID,
VSL.UPDATE_TIME,
VSL.VESSEL_NAME,
VSL.CALL_SIGN,
VSL.MMSI,
VSL.IMO_NUM,
VSL.LOA,
VSL.WIDTH,
VSL.NRT,
VSL.GRT,
VSL.DWT,
PORT.PORT_ID,
PORT.PORT_NAME
FROM
VSL_STATIC_DATA VSL
LEFT JOIN
TABLE_PORTS PORT
ON VSL.PORT_OF_REG_ID = PORT.PORT_ID
WHERE VSL.VESSEL_NAME LIKE :VSL_NAME || '%'
INTO
:VESSEL_ID,
:UPDATE_TIME,
:VESSEL_NAME,
:CALL_SIGN,
:MMSI,
:IMO,
:LOA,
:WIDTH,
:NRT,
:GRT,
:DWT,
:PORT_OF_REG_ID,
:PORT_OF_REG
DO
SUSPEND;
END;
这不使用索引。我用这个sql调用它:
select * from find_vessel_by_name( 'te', 10, 0)
任何人都可以指出我缺少的东西吗? 仅供参考,其目的是按名称实施船舶增量搜索。
答案 0 :(得分:2)
您可以尝试使用以:VSL_NAME 开头,而不是,例如:VSL_NAME || '%',但在这种情况下,您无法使用其他野人。
答案 1 :(得分:1)
VESSEL_NAME上的索引不能在存储过程中使用,因为绑定变量(可能还有||
操作 - 优化器有时并不完美。)
回想一下,计划计算一次,但对任何输入执行。
考虑例如find_vessel_by_name('%te',...)
- 这里索引没用。 find_vessel_by_name(NULL,...)
- 应该做什么?
您需要某种方法来强制使用索引。