mysql 查询 不等于1的,MySQL,作为1个查询,如果行不存在,则执行其他查询

对于首选项模块,我有“系统默认值”和“用户首选项”.

如果没有存储个人/用户首选项,请改用系统默认值.

这是我的系统偏好设置表:

mysql> desc rbl;

+-------------+---------------------+------+-----+---------+-------+

| Field | Type | Null | Key | Default | Extra |

+-------------+---------------------+------+-----+---------+-------+

| id | varchar(3) | NO | PRI | | |

| rbl_url | varchar(100) | NO | | | |

| description | varchar(100) | NO | | | |

| is_default | tinyint(1) unsigned | YES | | 1 | |

+-------------+---------------------+------+-----+---------+-------+

4 rows in set (0.00 sec)

来自系统偏好设置的示例数据:

mysql> select * from rbl;

+----+----------------------+------------------------------+------------+

| id | rbl_url | description | is_default |

+----+----------------------+------------------------------+------------+

| 1 | sbl-xbl.spamhaus.org | Spamhaus SBL-XBL | 1 |

| 2 | pbl.spamhaus.org | Spamhaus PBL | 1 |

| 3 | bl.spamcop.net | Spamcop Blacklist | 1 |

| 4 | rbl.example.com | Example RBL - not functional | 0 |

+----+----------------------+------------------------------+------------+

…并查询系统默认值:

mysql> SELECT rbl_url FROM rbl WHERE is_default='1';

+----------------------+

| rbl_url |

+----------------------+

| sbl-xbl.spamhaus.org |

| pbl.spamhaus.org |

| bl.spamcop.net |

+----------------------+

3 rows in set (0.01 sec)

到现在为止还挺好.

好.现在,我需要一个用户首选项表,然后我想到了:

mysql> desc rbl_pref;

+-----------+-----------------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+-----------+-----------------------+------+-----+---------+----------------+

| id | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |

| domain_id | mediumint(8) unsigned | NO | | NULL | |

| rbl_id | tinyint(1) unsigned | NO | | NULL | |

+-----------+-----------------------+------+-----+---------+----------------+

3 rows in set (0.00 sec)

(仅供参考-“用户”由“ domain_id”表示.)

让我们查看保存了个性化首选项的特定用户的首选项:

mysql> select * from rbl_pref where domain_id='2277';

+----+-----------+--------+

| id | domain_id | rbl_id |

+----+-----------+--------+

| 4 | 2277 | 1 |

| 5 | 2277 | 2 |

| 6 | 2277 | 4 |

+----+-----------+--------+

3 rows in set (0.00 sec)

再次,但格式更简单:

mysql> SELECT rbl.rbl_url FROM rbl_pref,rbl

WHERE rbl_pref.rbl_id=rbl.id AND domain_id='2277';

+----------------------+

| rbl_url |

+----------------------+

| sbl-xbl.spamhaus.org |

| pbl.spamhaus.org |

| rbl.example.com |

+----------------------+

3 rows in set (0.00 sec)

.. 到现在为止还挺好.如果用户存储了首选项,则会找到结果.

现在的问题示例是,用户1999没有自定义首选项.

我希望使用系统默认值来代替“空集”结果.

mysql> SELECT rbl.rbl_url FROM rbl_pref,rbl

WHERE rbl_pref.rbl_id=rbl.id AND domain_id='1999';

Empty set (0.00 sec)

我很高兴找到一个非常类似的问题:

mysql if row doesn’t exist, grab default value

但是,经过几天的反复试验和文档审查,我无法将答案翻译到此处.

像上面的问题一样,这必须作为单个MySQL查询来完成.我实际上不是从PHP进行此查询,而是从Exim宏进行查询(这是一种非常挑剔的语言,最好将它作为变量赋值给“一个衬里”,就像我在这里尝试做的那样.)

更新:尝试了以下@Biff McGriff建议的一种UNION查询类型.该表未显示在我的评论回复中,因此这里再次出现:

mysql> SELECT rbl.rbl_url FROM rbl_pref,rbl

WHERE rbl_pref.rbl_id=rbl.id AND domain_id='2277'

UNION SELECT rbl_url FROM rbl WHERE is_default='1';

+----------------------+

| rbl_url |

+----------------------+

| sbl-xbl.spamhaus.org |

| pbl.spamhaus.org |

| rbl.example.com |

| bl.spamcop.net |

+----------------------+

4 rows in set (0.00 sec)

如您在上面看到的,用户2277并未选择加入rbl_id 3(bl.spamcop.net),但是无论如何这还是会出现.

我的UNION查询似乎在做的是合并结果集.因此,user_pref充当全局默认值的“补充”,并且我假设/期望得到的结果集将与查询的一半匹配.

所以我现在的问题是,将其解决为“两个结果集”(UNION两侧的任一子查询)是否更好(或可能如何)?还是我真的需要在rbl_pref上添加一个新字段,例如“ enabled”.后者似乎更正确-我需要在rbl_pref中有一些东西来显式指定选择加入或选择退出(除了隐式的“那个pref不在这里-no rbl_id = 3-在过度覆盖的用户结果SET中”)

更新:全部设置,谢谢@Imre L,以及其他所有人.通过这个例子,我学到了一些东西.

解决方法:

注意:您必须在两个位置输入domain_id.

SELECT rbl.rbl_url FROM rbl

JOIN rbl_pref ON rbl_pref.rbl_id=rbl.id AND domain_id=2277

UNION

SELECT rbl.rbl_url FROM rbl

WHERE rbl.is_default

AND NOT EXISTS (SELECT 1 FROM rbl_pref WHERE domain_id=2277 LIMIT 1)

;

现在,UNION的另一侧将被优化,不可能在任何地方

您也不应将varchar(3)用于rbl.id,而应使用某种整数

并且最好与tinyint太小的与rbl_pref.rbl_id相同的类型

当您比较sql代码domain_id =’2277’中的整数字段时,请勿在常量整数周围使用’或’.

您大都可以摆脱它,但有时它可能会使mysql优化器感到困惑.

另外,为了获得最佳性能和一致性,我建议您添加索引:

ALTER TABLE rbl_pref

ADD UNIQUE INDEX ux_domain_rbl (domain_id, rbl_id);

标签:mysql

来源: https://codeday.me/bug/20191102/1990570.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CREATE FUNCTION getQueryResults (p_primaryKey VARCHAR(255)) RETURNS result SET @sql = CONCAT('SELECT * FROM table WHERE primary_key = ', p_primaryKey); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; RETURN result; ### 回答2: 要编写一个MySQL 8函数,参数是表的主键,返回查询语句的结果集,并且不报1064错误,可以使用以下代码: DELIMITER $$ CREATE FUNCTION getResults(pk INT) RETURNS VARCHAR(255) BEGIN DECLARE result VARCHAR(255); SET result = ''; -- 构建动态SQL查询语句 SET @sql = CONCAT('SELECT * FROM 表名 WHERE 主键列名 = ', pk); -- 执行动态SQL查询语句,并将结果保存到result变量中 PREPARE stmt FROM @sql; EXECUTE stmt INTO result; DEALLOCATE PREPARE stmt; RETURN result; END $$ DELIMITER ; 在代码中,需要将表名替换为实际的表名,主键列名替换为实际的主键列名。这个函数接受一个整数类型的参数pk,用于指定要查询的主键值。函数内部使用动态SQL语句构建了一个查询语句,并将其执行,将结果存储到result变量中。 在使用动态SQL的过程中,需要使用PREPARE语句准备查询语句,使用EXECUTE语句执行查询,并使用DEALLOCATE PREPARE语句释放资源。 最后,将查询结果作为字符串返回。 使用该函数的语法如下: SELECT getResults(主键值); 注意,这里的主键值需要是真实存在的主键值。 希望以上说明对您有所帮助。 ### 回答3: 在MySQL 8中编写一个函数,可以根据参数表的主键返回查询语句的结果集,并且不报1064错误。具体函数定义如下: ```sql DELIMITER // CREATE FUNCTION get_result_set(primary_key INT) RETURNS TABLE BEGIN RETURN ( SELECT * FROM your_table WHERE your_table.primary_key_column = primary_key ); END // DELIMITER ; ``` 请注意以下几点说明: 1. 将`your_table`替换为实际的表名,确保表名和列名的正确性。 2. 将`primary_key_column`替换为实际的主键列名。 3. 函数的参数名可以根据实际情况进修改,只需保证参数类型和表的主键类型一致即可。 4. 函数使用`RETURNS TABLE`语句来表示返回结果集。 5. 函数主体使用常规的SELECT语句进查询,根据传入的主键对应列进过滤。 6. 由于MySQL 8支持使用DELIMITER来定义存储过程和函数的结束符号,所以在创建函数之前使用`DELIMITER //`将结束符号更改为`//`,并在函数结束后使用`DELIMITER ;`将结束符号还原为默认的分号。 使用这个函数时,可以像查询表一样进操作,只需将函数当作表一样引用。例如: ```sql SELECT * FROM get_result_set(1); ``` 以上就是一个简单的MySQL 8函数的示例,它可以根据主键返回查询结果集,同时避免1064错误的出现。根据实际需求进适当修改即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值