5. 使用通配符进行过滤(%,_)

通配符:用来匹配值的一部分的特殊字符。

搜索模式:由字面值、通配符或两者组合构成的搜索条件。

1. 百分号(%)通配符

%表示任何字符出现任意次数(也能匹配0个字符)。例如,为了找出所有以jet开头的产品,可以使用:

SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE 'jet%';
可以多个位置使用多个通配符

例如,找出包含文本anvil的值

SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE '%anvil%';

注意:%不能匹配NULL,即WHERE prod_name LIKE '%'  !=NULL的!

2.下划线(_)通配符

下划线的用途与%一样,但下划线只匹配单个字符而不是多个字符。

SELECT prod_id,prod_name
FROM products
WHERE prod_name LIKE '_ ton anvil';
搜素的结果只有 1 ton anvil 、2 ton anvil  而没有  .5 ton anvil

与 %能匹配0个字符不一样,_总是匹配一个字符,不能多也不能少。

<think>好的,我现在需要分析用户提供的SQL查询语句,找出可能的问题并提供解决方法。首先,我会通读整个查询,了解其结构和目的。这个查询涉及多个表的连接,包括`pub_material_inventory`(别名为pmi)、`pub_material_rcv_detail`(别名为pmrd)和`pub_material_basic`(别名为pmb)。查询的目的是从这些表中选取相关字段,根据一些条件进行过滤。 首先,我会检查SQL的基本语法是否正确。例如,表别名是否正确使用,连接条件是否合理。注意到在INNER JOIN的ON子句中,用户使用了`PMI.material_rcv_id = pmrd.id`,这里PMI是全大写,而别名pmi是小写,这可能在某些数据库系统中导致问题,因为有些系统是大小写敏感的,尤其是在使用不同的数据库如PostgreSQL或MySQL时。比如,在Oracle中,如果表名或列名没有被引号包围,系统通常不区分大小写,但别名的大小写需要一致。这里pmi是别名,而PMI可能被视为不同的别名,导致错误,因此需要统一为小写的pmi。 接下来,检查连接条件是否正确。pmi和pmrd通过`material_rcv_id`和`id`连接,而pmb和pmi通过`id`和`material_id`连接,这看起来合理。但需要确认这些字段确实存在并且数据类型匹配,例如`pmi.material_rcv_id`是否与`pmrd.id`类型一致,否则可能导致隐式转换错误或性能问题。 然后是WHERE子句部分。用户使用了`pmi.del_flag = 0`、`pmi.storage_type != 3`和`pmi.id = 1898291185592590337`。这里需要注意`storage_type`字段是否允许NULL值,如果存在NULL,`storage_type != 3`将不会包含NULL的行,可能导致结果不符合预期。建议使用显式的处理,比如`(pmi.storage_type IS NULL OR pmi.storage_type != 3)`,但需要根据业务需求决定是否需要包含NULL的情况。 此外,`pmi.id = 1898291185592590337`这个条件中的ID值非常大,需要确认该字段是否为正确的数值类型(如BIGINT),避免整数溢出或类型不匹配的问题。如果该字段是字符串类型,则应该用引号包围,但通常ID字段是数值型,这里可能没问题,但值得检查表结构确认。 关于性能问题,由于查询中使用了多个INNER JOIN,且WHERE条件中有对pmi.id的精确匹配,如果该字段有索引,查询应该很快。但如果没有索引,尤其是在大表上,可能会导致全表扫描,影响性能。需要确认pmi.id是否有主键或索引,pmrd.id和pmb.id是否也有索引,以优化连接操作。 另外,字段`pmrd.del_flag = 0`被放在ON子句中而不是WHERE子句,这会影响连接的结果。ON子句中的条件在连接时应用,而WHERE子句在连接后过滤。这里可能没有问题,但需要根据业务逻辑确认是否正确,比如是否需要在连接时就排除pmrd中已删除的记录,还是应该在所有连接完成后过滤。如果pmrd.del_flag只影响pmrd表的记录,放在ON子句是正确的做法。 还有,SELECT子句中使用了`pmrd.*`,这会选取pmrd表的所有字段。虽然方便,但可能导致返回不必要的列,增加数据传输的开销,尤其是在跨网络查询时。建议明确列出需要的字段,避免使用通配符,同时也能减少未来表结构变更导致的问题。 另外,检查是否有字段名冲突,比如多个表中可能存在相同名称的字段,如id,这时候使用别名可以避免歧义。但用户已经为各个表指定了别名,并且在选择pmi.id时用了AS重命名,所以此处应该没问题。 总结可能的问题点: 1. 表别名的大小写不一致(PMI vs pmi)。 2. WHERE条件中对NULL值的处理可能不严谨。 3. pmrd.*可能导致性能或维护问题。 4. 确认连接字段的数据类型是否匹配。 5. 索引是否到位,影响查询性能。 6. 大数值ID的字段类型是否正确。 针对这些问题,逐步给出解决方案,并提醒用户检查表结构和索引,以及字段是否存在NULL值的情况。同时,建议优化SELECT子句,明确列出所需字段,避免使用通配符。</think>### SQL查询问题分析与解决方法 #### 1. **表别名大小写不一致问题** 在`INNER JOIN pub_material_rcv_detail pmrd`的ON条件中,使用了`PMI.material_rcv_id`,但表别名定义为小写的`pmi`。在部分数据库(如Oracle)中,若表名或别名未被引号包裹,系统可能不区分大小写,但保持一致性可避免潜在问题。 **修改建议**: ```sql ON pmi.material_rcv_id = pmrd.id -- 统一使用小写别名 ``` #### 2. **WHERE条件对NULL值的处理** 条件`pmi.storage_type != 3`会排除`storage_type`为NULL的行。若业务允许NULL值存在且需要包含这些记录,需显式处理: ```sql WHERE ... AND (pmi.storage_type IS NULL OR pmi.storage_type != 3) ``` #### 3. **避免使用`pmrd.*`通配符** `pmrd.*`会返回`pub_material_rcv_detail`表所有字段,可能导致以下问题: - **数据传输开销增加**:尤其是字段多或数据量大时。 - **字段冲突风险**:若多表有同名字段,需用别名区分。 **修改建议**: 明确列出所需字段,例如: ```sql SELECT ..., pmrd.field1, pmrd.field2, ... ``` #### 4. **连接字段类型匹配** 需确认以下字段类型是否一致: - `pmi.material_rcv_id`与`pmrd.id` - `pmb.id`与`pmi.material_id` 若类型不匹配(如VARCHAR与INT),会导致隐式转换,可能引发错误或性能问题[^2]。 #### 5. **索引缺失导致性能问题** - **WHERE条件优化**:`pmi.id = 1898291185592590337`若`pmi.id`是主键或唯一索引,查询效率较高;若无索引,需添加。 - **JOIN字段索引**:为`pmrd.id`和`pmb.id`添加索引可加速连接操作。 #### 6. **大数值ID的字段类型** `pmi.id = 1898291185592590337`的值为19位,需确认字段类型是否为`BIGINT`或`NUMBER(19)`,避免整数溢出。 --- ### 优化后的SQL示例 ```sql SELECT pmi.checker, pmi.check_time, pmi.check_remark, pmi.check_status, pmi.auditer, pmi.audit_time, pmi.audit_remark, pmrd.specific_field1, pmrd.specific_field2, -- 替换为实际需要字段 pmb.material_no, pmb.material_name, pmb.manu_facturer, pmb.model, pmb.pu_unit, pmi.material_stock_code, pmb.supplier_name, pmb.is_product, pmi.id AS material_inventory_id, pmi.quantity, pmi.container_id FROM pub_material_inventory pmi INNER JOIN pub_material_rcv_detail pmrd ON pmi.material_rcv_id = pmrd.id -- 修正别名大小写 AND pmrd.del_flag = 0 INNER JOIN pub_material_basic pmb ON pmb.id = pmi.material_id WHERE pmi.del_flag = 0 AND (pmi.storage_type IS NULL OR pmi.storage_type != 3) -- 处理NULL值 AND pmi.id = 1898291185592590337; ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值