mysql查询在一张表不在另外一张表的记录

本文详细介绍了MySQL中的左连接(LEFT JOIN)用法,并通过实例对比了不同类型的连接操作,包括左连接、右连接及内连接等,帮助读者理解并正确应用这些SQL连接技巧。
mysql查询在一张表不在另外一张表的记录
 
问题: 
 
查询一个表(tb1)的字段记录不在另一个表(tb2)中   
  条件:tb1的字段key的值不在tbl2表中   
  ----------------------    
最原始的写法:   
  select   A.*   from   tbl1 A where   A.key   not   in   (select   key   from   tbl2)      
  
如果tbl2表中数据量很大,比如数据上百万条,每次都这样匹配效率会非常低。    
   
 
解决问题: 
 
SELECT tb1.* FROM tb1 LEFT JOIN tb2 ON tb1.id=tb2.id WHERE tb2.id IS NULL;
 

 
关于sql语句中的连接(join)关键字,是较为常用而又不太容易理解的关键字,下面这个例子 
 
给出了一个简单的解释,相信会对你有所启示。 
 
 
--建表table1,table2: 
create table table1(id int,name varchar(10)) 
create table table2(id int,score int) 
insert into table1 select 1,'lee' 
insert into table1 select 2,'zhang' 
insert into table1 select 4,'wang' 
insert into table2 select 1,90 
insert into table2 select 2,100 
insert into table2 select 3,70 
如表 
------------------------------------------------- 
 table1  | table2  | 
------------------------------------------------- 
id  name |id  score | 
1  lee     |1  90 | 
2  zhang |2  100 | 
4  wang |3  70 | 
------------------------------------------------- 
 
以下均在查询分析器中执行 
 
一、外连接 
1.概念:包括左向外联接、右向外联接或完整外部联接 
 
2.左连接:left join 或 left outer join 
(1)左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹 
 
配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列 
 
均为空值(null)。 
(2)sql语句 
select * from table1 left join table2 on table1.id=table2.id 
-------------结果------------- 
id name id score 
------------------------------ 
1 lee 1 90 
2 zhang 2 100 
4 wang NULL NULL 
------------------------------ 
注释:包含table1的所有子句,根据指定条件返回table2相应的字段,不符合的以null显示 
 
3.右连接:right join 或 right outer join 
(1)右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有 
 
匹配行,则将为左表返回空值。 
(2)sql语句 
select * from table1 right join table2 on table1.id=table2.id 
-------------结果------------- 
id name id score 
------------------------------ 
1 lee 1 90 
2 zhang 2 100 
NULL NULL 3 70 
------------------------------ 
注释:包含table2的所有子句,根据指定条件返回table1相应的字段,不符合的以null显示 
 
4.完整外部联接:full join 或 full outer join 
(1)完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表 
 
的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。 
(2)sql语句 
select * from table1 full join table2 on table1.id=table2.id 
-------------结果------------- 
id name id score 
------------------------------ 
1 lee 1 90 
2 zhang 2 100 
4 wang NULL NULL 
NULL NULL 3 70 
------------------------------ 
注释:返回左右连接的和(见上左、右连接) 
 
二、内连接 
1.概念:内联接是用比较运算符比较要联接列的值的联接 
 
2.内连接:join 或 inner join 
 
3.sql语句 
select * from table1 join table2 on table1.id=table2.id 
-------------结果------------- 
id name id score 
------------------------------ 
1 lee 1 90 
2 zhang 2 100 
------------------------------ 
注释:只返回符合条件的table1和table2的列 
 
4.等价(与下列执行效果相同) 
A:select a.*,b.* from table1 a,table2 b where a.id=b.id 
B:select * from table1 cross join table2 where table1.id=table2.id  (注:cross join 
 
后加条件只能用where,不能用on) 
 
三、交叉连接(完全) 
 
1.概念:没有 WHERE 子句的交叉联接将产生联接所涉及的表的笛卡尔积。第一个表的行数乘以 
 
第二个表的行数等于笛卡尔积结果集的大小。(table1和table2交叉连接产生3*3=9条记录) 
 
2.交叉连接:cross join (不带条件where...) 
 
3.sql语句 
select * from table1 cross join table2 
-------------结果------------- 
id name id score 
------------------------------ 
1 lee 1 90 
2 zhang 1 90 
4 wang 1 90 
1 lee 2 100 
2 zhang 2 100 
4 wang 2 100 
1 lee 3 70 
2 zhang 3 70 
4 wang 3 70 
------------------------------ 
注释:返回3*3=9条记录,即笛卡尔积 
 
4.等价(与下列执行效果相同) 
A:select * from table1,table2 
 
 
左连接如果要关联三张表,那么接连使用两个left outer join和on组合。
<think>我们正在处理用户关于查询MySQL中某张的SQL执行记录的问题。根据用户需求,我们需要找到方法或解决方案来追踪针对特定执行过的SQL语句。首先,我们需要明确:MySQL本身并提供内置的功能来记录所有执行的SQL语句,尤其是针对特定查询记录。但是,我们可以通过一些配置或使用第三方工具来实现类似的功能。以下是几种可行的方法:###方法1:启用MySQL的通用查询日志(GeneralQueryLog)通用查询日志会记录所有连接到MySQL的客户端执行的SQL语句。我们可以通过配置来启用它,并指定日志文件的位置。**步骤:**1.**修改MySQL配置文件**(通常是`my.cnf`或`my.ini`),在`[mysqld]`部分添加以下配置:```general_log=1general_log_file=/path/to/query.log```其中`/path/to/query.log`是你希望存储日志的路径。2.**重启MySQL服务**使配置生效。3.之后,所有执行的SQL语句都会被记录到指定的日志文件中。4.如果要筛选针对特定(例如名为`your_table`)的SQL语句,可以使用文本处理工具(如`grep`)来过滤日志:```bashgrep'your_table'/path/to/query.log```**注意:**这种方法会记录所有查询,可能会对性能产生影响,并占用大量磁盘空间。因此,建议仅在需要诊断问题时临时开启,并在完成之后关闭(设置`general_log=0`并重启MySQL,或者动态设置:`SETGLOBALgeneral_log='OFF';`)。###方法2:使用MySQL的慢查询日志(SlowQueryLog)慢查询日志主要记录执行时间超过指定阈值的查询。虽然它是为了记录所有查询而设计的,但我们可以将阈值设置为0来记录所有查询。**步骤:**1.**修改配置文件**,在`[mysqld]`部分添加:```slow_query_log=1slow_query_log_file=/path/to/slow-query.loglong_query_time=0```设置`long_query_time=0`记录所有查询。2.**重启MySQL服务**。3.同样,可以使用`grep`等工具来过滤特定查询。**注意:**与通用查询日志类似,记录所有查询可能会对性能和磁盘空间有较大影响。###方法3:使用审计插件(如PerconaAuditLogPlugin,MariaDBAuditPlugin)MySQL企业版提供了审计插件,但社区版没有。过,可以使用Percona或MariaDB的审计插件(如果使用的是PerconaServer或MariaDB)。这些插件可以提供更灵活的审计功能,包括按名过滤。以PerconaAuditPlugin为例:1.安装插件(如果尚未安装):```sqlINSTALLPLUGINaudit_logSONAME'audit_log.so';```2.配置审计规则。例如,在配置文件中添加:```[mysqld]audit_log_format=JSONaudit_log_policy=ALLaudit_log_include_databases=your_database```但是,该插件默认并支持按名过滤。我们可以通过编写脚本来解析日志并提取针对特定查询。###方法4:使用触发器(推荐)为上的每个操作(INSERT,UPDATE,DELETE)创建触发器,并在触发器中记录操作信息到另一张。但这种方法无法记录SELECT查询,而且只能记录定义触发器之后的操作,同时会带来额外的性能开销。###方法5:使用中间件或代理在应用程序和MySQL之间使用代理(如MaxScale、ProxySQL)或中间件,这些工具可以记录所有经过的SQL语句。然后,我们可以通过配置这些工具来记录和过滤特定查询。###总结对于大多数情况,临时开启通用查询日志或慢查询日志(设置`long_query_time=0`)是最简单的方法。但需要注意性能影响和日志管理。如果用户需要长期监控特定查询,建议考虑使用审计插件或中间件方案。###动态设置通用查询日志(无需重启)如果用户想重启MySQL,可以动态设置通用查询日志(注意:需要SUPER权限):```sqlSETGLOBALgeneral_log='ON';SETGLOBALgeneral_log_file='/path/to/query.log';```关闭时:```sqlSETGLOBALgeneral_log='OFF';```###注意事项-确保日志文件路径MySQL服务器有写入权限。-日志文件会断增长,需要定期清理或轮转。§§相关问题§§1.如何动态开启和关闭MySQL的通用查询日志?2.如何分析MySQL的慢查询日志?3.MySQL有哪些审计插件可以使用?4.如何安全地清理MySQL的日志文件?</think>### 如何在 MySQL查询某张的 SQL 执行记录 MySQL 本身直接提供查询特定历史 SQL 执行记录的功能,但可通过以下方法实现追踪: #### 方法 1:启用通用查询日志(推荐) 1. **开启日志**(需 `SUPER` 权限): ```sql -- 动态开启(无需重启) SET GLOBAL general_log = 'ON'; SET GLOBAL log_output = 'FILE'; -- 输出到文件 SET GLOBAL general_log_file = '/var/log/mysql/query.log'; ``` *或在 `my.cnf` 中配置:* ```ini [mysqld] general_log = 1 general_log_file = /var/log/mysql/query.log ``` 2. **查询特定的 SQL**: ```bash grep "your_table_name" /var/log/mysql/query.log ``` **注意**:会记录**所有** SQL 语句,需定期清理日志[^1]。 #### 方法 2:使用性能模式(MySQL 5.7+) 1. **启用性能监控**: ```sql UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_statements%'; ``` 2. **查看历史 SQL**: ```sql SELECT SQL_TEXT, SCHEMA_NAME, TIMER_START FROM performance_schema.events_statements_history WHERE SQL_TEXT LIKE '%your_table_name%'; ``` *仅记录最近语句(默认保留量有限)[^2]。 #### 方法 3:审计插件(企业级方案) - **MySQL Enterprise Audit**:商业版支持级审计 - **Percona/MariaDB 插件**:开源替代方案 ```sql INSTALL PLUGIN audit_log SONAME 'audit_log.so'; SET GLOBAL audit_log_policy = 'ALL'; ``` #### 方法 4:应用程序层记录 在代码中拦截 SQL 语句(如通过 ORM 的日志功能或中间件),示例伪代码: ```python # Python SQLAlchemy 示例 import logging logging.basicConfig(filename='sql.log') engine = create_engine("mysql://user:pass@host/db", echo=True) ``` > **重要建议**: > 1. 生产环境优先用**性能模式**(低开销) > 2. 调试时用**通用日志**(记录完整) > 3. 长期审计需**企业版插件**或**应用层记录** > 4. 日志敏感!确保访问权限控制
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值