例题1
下面关于 InnoDB 存储引擎和 MyISAM 存储引擎正确的是()
A InnoDB 支持行级锁和表级锁,而 MyISAM 支持表级锁
B InnoDB 支持全文索引,而 MyISAM 不支持全文索引
C InnoDB 不支持事务,而 MyISAM 支持事务
D InnoDB 不支持外键,而 MyISAM 支持外键
解析
这道题目考察的是 MySQL 中 InnoDB 和 MyISAM 两种存储引擎的区别
- A InnoDB 支持 行级锁 和 表级锁,其中行级锁是 InnoDB 的一个重要特性,有助于提高并发性能。
MyISAM 只支持表级锁,每次对表进行增删改操作时,都会锁住整个表,限制了并发处理能力。 - B MyISAM 比 InnoDB 更早支持全文索引(Full-Text Index)。MyISAM 早期版本就已经支持全文索引,适用于文本搜索功能。
InnoDB 从 MySQL 5.6 开始支持全文索引,但这是相对较新的功能。 - C InnoDB 支持事务,这也是它的一个关键特性,能够提供 ACID(原子性、一致性、隔离性、持久性)保障,使其适合需要事务处理的应用场景。
MyISAM 不支持事务,它不保证数据的回滚和一致性,因此不适合事务性要求较高的场景。 - D InnoDB 支持外键,可以强制参照完整性约束,以维护表之间的数据一致性。
MyISAM 不支持外键,其表结构设计相对简单,没有外键约束。
例题2
有一张电话表(telephones),id是主键,send_id表示打电话人的id,receive_id表示接电话人的id,type表示电话是否打成功:
还有一张用户表(users),id也是主键,is_blacklist列中的1 代表该用户是骚扰用户,即他的电话不会打成功,会被系统拦截。
现要查询每天的正常用户给正常用户打电话,无法接通(可能是信号不好、电话欠费等原因导致)的概率,结果保留到小数点后两位,并按日期降序排列。比如上面示例就会得到如下结果
(注意: sqlite 1/2得到的不是0.5,得到的是0,只有1*1.0/2才会得到0.5,sqlite四舍五入的函数为round)
下列sqlite查询语句正确的是()
A
B
C
D
解析
A
SELECT
t.date,
ROUND(
SUM(
CASE WHEN t.type = 'no_completed' THEN 1 ELSE 0 END
) * 1.0 / COUNT(t.type),
2) AS p
FROM
telephones t
JOIN users u1 ON t.send_id = u1.id
AND u1.is_blacklist = 0
JOIN users u2 ON t.receive_id = u2.id
AND u2.is_blacklist = 0
GROUP BY
t.date
ORDER BY
t.date DESC;
SUM(CASE WHEN t.type = 'no_completed' THEN 1 ELSE 0 END)
这段代码通过CASE
语句计算通话失败的数量,即type
为'no_completed'
时加1
,否则加0
。* 1.0 / COUNT(t.type)
用总的失败通话数除以当天所有通话的总数,* 1.0
确保执行浮点数除法,而不是整数除法,从而计算出失败通话的比例。JOIN users u1
andJOIN users u2
将telephones
表中的send_id
和receive_id
分别与users
表的id
连接,确保通话双方都不是黑名单用户(is_blacklist = 0)
,这样只有符合条件的通话才会被计算ROUND(..., 2)
使用ROUND
函数将结果保留两位小数GROUP BY t.date
和ORDER BY t.date DESC
按照date
分组和降序排列,保证每一天的通话比例分别计算并按日期从最近到最远排序
B
SELECT
t.date,
ROUND(
SUM(
CASE t.type WHEN 'completed' THEN 0 ELSE 1 END
) * 1.0 / COUNT(t.type),
2) AS p
FROM
telephones AS t,
users as u
WHERE
t.send_id = u.id
AND t.receive_id = u.id
AND u.is_blacklist = 0
GROUP BY
t.date
ORDER BY
t.date DESC;
SUM(CASE t.type WHEN 'completed' THEN 0 ELSE 1 END)
这里试图通过CASE t.type
来判断通话的类型,但CASE
语法错误。应该用CASE WHEN
而不是CASE t.type WHEN
。
此外,'completed'
代表通话成功,0
对应成功通话,1
对应其他情况(失败)。逻辑上与题意相符。- 错误的表连接
FROM telephones AS t, users as u
:这里在 WHERE 子句中试图将send_id
和receive_id
都连接到同一个用户表users
,这不符合逻辑。因为send_id
和receive_id
分别代表打电话人和接电话人,它们应该连接到两个用户实体,而不是同一个用户。
逻辑上应该像 A 选项那样,分开send_id
和receive_id
对应到不同的users
表中的用户。
C
SELECT
t.date,
ROUND(
SUM(
CASE WHEN t.type = 'no_completed' THEN 1 ELSE 0 END
) / COUNT(t.type),
2) AS p
FROM
telephones t
JOIN users u1 ON t.send_id = u1.id
AND u1.is_blacklist = 0
JOIN users u2 ON t.receive_id = u2.id
AND u2.is_blacklist = 0
GROUP BY
t.date
ORDER BY
t.date DESC;
- 缺少
* 1.0
这里的SUM(...) / COUNT(t.type)
没有乘以1.0
,导致在某些数据库中可能会执行整数除法,而不是浮点数除法,可能会出现计算精度丢失的问题。
D
SELECT
t.date,
ROUND(
SUM(
CASE WHEN t.type = 'no_completed' THEN 1 ELSE 0 END
) * 1.0 / COUNT(t.type),
2) AS p
FROM
telephones
JOIN users u1 ON t.send_id = u1.id
AND u1.is_blacklist = 0
JOIN users u2 ON t.receive_id = u2.id
AND u2.is_blacklist = 0
GROUP BY
t.date
ORDER BY
t.date DESC;
- 没有指定
telephones
的别名
查询中的FROM telephones
没有给表telephones
指定别名t
,但是在后面的查询中使用了t.send_id
和t.receive_id
,这会导致 SQL 报错,找不到表t
例题3
在MySQL中可以用来执行预处理语句的是()
A execute
B prepare
C deallocate
D using
解析
PREPARE
语句准备好一条SQL语句,并分配给这条SQL语句一个名字供之后调用。准备好的SQL语句通过EXECUTE
命令执行,通过DEALLOCATE PREPARE
或者DEALLOCATE
命令释放掉。
补充
预处理
语句的名字不区分大小写。准备好的SQL语句名字可以是字符串,也可以是用户指定的包含SQL文本的变量。PREPARE
中的SQL文本必须代表一条单独的SQL语句而不能是多条SQL语句。在SQL语句中,?
字符用来作为后面执行查询使用的一个参数。?
不能加上引号,即使打算将它们绑定到字符变量中也不可以 。