11. 使用MySQL之使用数据处理函数

news/2024/10/25 1:22:49

1. 函数

与其他大多数计算机语言一样,SQL支持利用函数来处理数据。

函数一般是在数据上执行的,它给数据的转换和处理提供了方便。

在前一章中用来去掉串尾空格的RTrim()就是一个函数的例子。

补充:

函数没有SQL的可移植性强

能运行在多个系统上的代码称为可移植的(portable)

相对来说,多数SQL语句是可移植的,在SQL实现之间有差异时,这些差异通常不那么难处理。而函数的可移植性却不强。几乎每种主要的DBMS的实现都支持其他实现不支持的函数,而且有时差异还很大。

为了代码的可移植,许多SQL程序员不赞成使用特殊实现的功能。虽然这样做很有好处,但不总是利于应用程序的性能。如果不使用这些函数,编写某些应用程序代码会很艰难。必须利用其他方法来实现DBMS非常有效地完成的工作。

如果你决定使用函数,应该保证做好代码注释,以便以后你(或其他人)能确切地知道所编写SQL代码的含义。

2. 使用函数

大多数SQL实现支持以下类型的函数。

  • 用于处理文本串(如删除或填充值,转换值为大写或小写)的文本函数。

  • 用于在数值数据上进行算术操作(如返回绝对值,进行代数运算)的数值函数。

  • 用于处理日期和时间值并从这些值中提取特定成分(例如,返回两个日期之差,检查日期有效性等)的日期和时间函数。

  • 返回DBMS正使用的特殊信息(如返回用户登录信息,检查版本细节)的系统函数。

2.1 文本处理函数

上一章中我们已经看过一个文本处理函数的例子,其中使用 RTrim()函数来去除列值右边的空格。

下面是另一个例子,这次使用 Upper() 函数:

select vend_name, upper(vend_name) as vend_name_upcase
from vendors
order by vend_name;

输出如下:

img

Upper()将文本转换为大写,因此本例子中每个供应商都列出两次,第一次为vendors表中存储的值,第二次作为列vend_name_upcase转换为大写。

下面列出了某些常用的文本处理函数。

img
img

  • SOUNDEX做进一步的解释:

    SOUNDEX是一个将任何文本串转换为描述其语音表示的字母数字模式的算法。

    SOUNDEX考虑了类似的发音字符和音节,使得能对串进行发音比较而不是字母比较。

    虽然SOUNDEX不是SQL概念,但MySQL(就像多数DBMS一样)都提供对
    SOUNDEX的支持。

    下面给出一个使用Soundex()函数的例子。

    customers表中有一个顾客Coyote Inc.,其联系名为Y Lee。但如果这是输入错误,此联系名实际应该是Y Lie,怎么办?显然,按正确的联系名搜索不会返回数据,如下所示:

    select cust_name, cust_contact
    from customers
    where cust_contact = 'Y Lie';
    

    输出如下:

    img

    现在试一下使用Soundex()函数进行搜索,它匹配所有发音类似于Y Lie的联系名:

    select cust_name, cust_contact
    from customers
    where soundex(cust_contact) = soundex('Y Lie');
    

    输出如下:

    img

    在这个例子中,WHERE子句使用Soundex()函数来转换cust_contact列值和搜索串为它们的SOUNDEX值。因为Y.Lee和Y.Lie发音相似,所以它们的SOUNDEX值匹配,因此WHERE子句正确地过滤出了所需的数据。

  • Left()做进一步的解释:

    在 MySQL 中,LEFT() 函数用于从字符串的左边提取指定长度的子字符串。

    语法

    LEFT(string, length)
    
    • string:要从中提取子字符串的字符串。

    • length:要提取的字符数。

    举例

    SELECT LEFT('Hello, World!', 5);  -- 输出 'Hello'
    

    即从字符串 'Hello, World!' 中提取从左边开始的 5 个字符。

    再比如,如果你有一个存储姓名的表 students,并且想要提取每个学生姓名的前两个字符,你可以这样写:

    SELECT LEFT(name, 2) FROM students;
    

    这个查询会返回每个姓名的前两个字符。

    注意

    在 MySQL 中,LEFT() 函数同样可以处理中文字符。它会根据字符的个数(而不是字节数)来提取中文字符。

    举个例子:

    img

    第一条select语句的结果如下:

    img

    第二条select语句的结果如下:

    img

  • Right()做进一步的解释:

    在 MySQL 中,RIGHT() 函数用于从字符串的右边提取指定长度的子字符串。

    其余的和Left()一样,不赘叙

2.2 日期和时间处理函数

日期和时间采用相应的数据类型和特殊的格式存储,以便能快速和有效地排序或过滤,并且节省物理存储空间。

插入一个题外话:

MySQL 提供了几种专门用于日期和时间的数据类型,能够以高效的方式存储和操作这些数据。以下是主要的数据类型以及它们的格式:

  1. DATE 类型

    用于存储日期(不包括时间部分),格式为 'YYYY-MM-DD'。

    存储大小:3 字节。

    范围:1000-01-01 到 9999-12-31。

    比如:

    DATE '2024-10-24'
    
  2. TIME 类型

    用于存储时间(不包括日期部分),格式为 'HH:MM:SS'。

    存储大小:3 字节。

    范围:'-838:59:59' 到 '838:59:59'(支持负时间表示持续时间的情况)

    比如:

    TIME '14:30:45'
    
  3. DATETIME 类型

    用于存储日期和时间的组合,格式为 'YYYY-MM-DD HH:MM:SS'。

    存储大小:8 字节。

    范围:1000-01-01 00:00:00 到 9999-12-31 23:59:59。

    比如:

    DATETIME '2024-10-24 14:30:45'
    
  4. TIMESTAMP 类型

    用于存储自 1970-01-01 00:00:00 UTC(Unix Epoch 时间)以来的秒数。与 DATETIME 类似,格式为 'YYYY-MM-DD HH:MM:SS'。

    存储大小:4 字节(比 DATETIME 占用空间更小)。

    范围:1970-01-01 00:00:01 UTC 到 2038-01-19 03:14:07 UTC。

    TIMESTAMP 可以随着时区的不同而自动调整,因此常用于记录操作的时间戳(例如记录插入或更新时的时间)。

    比如:

    TIMESTAMP '2024-10-24 14:30:45'
    
  5. YEAR 类型

    用于存储年份,格式为 'YYYY'。

    存储大小:1 字节。

    范围:1901 到 2155。

    比如:

    YEAR '2024'
    

    一个好玩的

    如果是year '2156'呢?MySQL会做什么?

    在 MySQL 中,YEAR 数据类型的有效范围是 1901 到 2155,因此 YEAR '2156' 是超出有效范围的。如果你尝试将 '2156' 存储在 YEAR 类型的字段中,会导致错误或数据被截断。

    处理超出范围的值:

    • 如果你尝试插入 YEAR '2156',MySQL 会产生一个警告或错误,具体行为取决于 SQL 模式的设置。如果是严格模式(STRICT 模式),则会抛出错误并阻止插入。如果不是严格模式,MySQL 可能会插入一个默认值(通常为 0000),并发出警告。

    解决方案:

    • 保持在范围内:在使用 YEAR 类型时,确保年份在 1901 到 2155 之间。如果需要存储 2156 或更大的年份,你可以考虑使用其他数据类型,如 INT 或 VARCHAR,以手动存储年份。

    • 使用 DATETIME 或 TIMESTAMP:如果你需要存储更大范围的日期和时间,可以考虑使用 DATETIME 数据类型,虽然它占用更多的存储空间,但它能表示更大范围的年份(1000 到 9999)。

  6. 数据类型和格式的优势:

    • 高效的存储:

      这些数据类型经过优化,采用内部的二进制表示方式,从而节省存储空间。例如,DATE 只占 3 个字节,而一个字符型字符串表示同样的日期需要更多的空间。

    • 高效的排序和过滤:

      使用内置的日期和时间数据类型,可以高效地进行排序和过滤操作,而不需要额外的转换。

    • 特殊的格式:

      MySQL 在后台使用一种二进制格式来存储日期和时间,使得它们可以快速解析和计算。例如,虽然 DATETIME 看起来像 'YYYY-MM-DD HH:MM:SS',但它实际是以压缩的方式存储,并且能够快速比较和操作。

回归正题:

一般,应用程序不使用用来存储日期和时间的格式,因此日期和时间函数总是被用来读取、统计和处理这些值。由于这个原因,日期和时间函数在MySQL语言中具有重要的作用。

表11-2列出了某些常用的日期和时间处理函数。

img

迄今为止,我们都是用比较数值和文本的WHERE子句过滤数据,但数据经常需要用日期进行过滤。用日期进行过滤需要注意一些别的问题和使用特殊的MySQL函数

首先需要注意的是MySQL使用的日期格式。

无论你什么时候指定一个日期,不管是插入或更新表值还是用WHERE子句进行过滤,日期必须为格式yyyy-mm-dd。因此,2005年9月1日,给出为2005-09-01。

虽然其他的日期格式可能也行,但这是首选的日期格式,因为它排除了多义性(如,04/05/06是2006年5月4日或2006年4月5日或2004年5月6日或……)

  • 补充:

    应该总是使用4位数字的年份:

    支持2位数字的年份,MySQL处理00-69为2000-2069,处理70-99为1970-1999。虽然它们可能是打算要的年份,但使用完整的4位数字年份更可靠,因为MySQL不必做出任何假定。

因此,基本的日期比较应该很简单:

select cust_id, order_num
from orders
where order_date = '2005-09-01';

输出如下:

img

此SELECT语句正常运行。它检索出一个订单记录,该订单记录的order_date为2005-09-01。

但是,使用WHERE order_date = '2005-09-01'可靠吗?

order_ date的数据类型为datetime。这种类型存储日期及时间值。样例表中的值全都具有时间值00:00:00。如下图:

img

但实际中很可能并不总是这样。如果用当前日期和时间存储订单日期(因此你不仅知道订单日期,还知道下订单当天的时间), 怎么办 ?

比如,存储的 order_date 值为 2005-09-01 11:30:05,则 WHERE order_date = '2005-09-01'失败。即使给出具有该日期的一行,也不会把它检索出来,因为WHERE匹配失败。

解决办法是指示MySQL仅将给出的日期与列中的日期部分进行比较,而不是将给出的日期与整个列值进行比较。为此,必须使用 Date()函数。Date(order_date)指示MySQL仅提取列的日期部分。

更可靠的SELECT语句为:

select cust_id, order_num
from orders
where date(order_date) = '2005-09-01';

输出如下:

img

插一句题外话

自己试了下DateDiff()的写法

img

补充:

如果要的是日期,请使用Date()

如果你想要的仅是日期,则使用Date()是一个良好的习惯,即使你知道相应的列只包含日期也是如此。这样,如果由于某种原因表中以后有日期和时间值,你的SQL代码也不用改变。当然,也存在一个Time()函数,在你只想要时间时应该使用它。 Date()Time()都是在MySQL 4.1.1中第一次引入的。

不过,还有一种日期比较需要说明。

如果你想检索出2005年9月下的所有订单,怎么办?简单的相等测试不行,因为它也要匹配月份中的天数。

有几种解决办法,其中之一如下所示:

select cust_id, order_num
from orders
where date(order_date) between '2005-09-01' and '2005-09-30';

输出如下:

img

其中,BETWEEN操作符用来把2005-09-01和2005-09-30定义为一个要匹配的日期范围。

还有另外一种办法(一种不需要记住每个月中有多少天或不需要操心闰年2月的办法):

select cust_id, order_num
from orders
where year(order_date) = 2005 and month(order_date) = 9;

输出如下:

img

Year()是一个从日期(或日期时间)中返回年份的函数。类似,Month()从日期中返回月份。因此,WHERE Year(order_date)= 2005 AND Month(order_date) = 9检索出order_date为2005年9月的所有行。

补充:

  • MySQL的版本差异:

    MySQL 4.1.1中增加了许多日期和时间函数。如果你使用的是更早的MySQL版本,应该查阅具体的文档以确定可以使用哪些函数。

  • DATE_SUB()DATEDIFF()的区别:

    DATE_SUB() 和 DATEDIFF() 都是 MySQL 中用于操作日期的函数,但它们的功能完全不同:

    • DATE_SUB() 用于从日期中减去一个时间间隔(如天、月、年等),返回一个新的日期。

      • 语法:

        DATE_SUB(date, INTERVAL expr unit)
        
        • date: 原始日期。

        • expr: 时间间隔的数量。

        • unit: 时间单位(如 DAY, MONTH, YEAR 等)。

      • 功能:从日期减去指定的时间间隔,返回一个新的日期。

      • 示例: 从当前日期减去 7 天:

        select date_sub(curdate(), interval 7 day);
        

        输出如下:

        img

    • DATEDIFF() 用于计算两个日期之间的天数差,返回一个整数值,表示两个日期之间相差多少天。

      • 语法:

        DATEDIFF(date1, date2)
        
        • date1 和 date2: 两个日期,用于计算相差的天数。

        • 结果为 date1 - date2,即 date1 减去 date2。

      • 功能:计算两个日期之间的天数差,并返回整数结果。

      • 示例: 计算两个日期之间相差多少天:

        select datediff('2024-10-25', '2024-10-20')
        

        输出如下:

        img

  • ADDDATE()DATE_ADD() 的区别:

    在 MySQL 中,ADDDATE()DATE_ADD() 这两个函数都用于向日期添加时间间隔,功能非常相似,主要的区别在于语法上的细微差异。

    • ADDDATE() 用于向日期添加天数或指定的时间间隔。该函数有两种不同的用法:

      • 可以直接添加天数。

      • 也可以与 INTERVAL 一起使用,添加年、月、天等不同的时间单位。

        语法:

        1. 直接添加天数:

          ADDDATE(date, number_of_days)
          
          • date: 要修改的日期。

          • number_of_days: 添加的天数,必须是整数

        2. 使用 INTERVAL:

          ADDDATE(date, INTERVAL expr unit)
          
          • date: 要修改的日期。

          • expr: 时间间隔的数量。

          • unit: 时间单位(如 DAY, MONTH, YEAR 等)。

    • DATE_ADD() 函数与 ADDDATE() 的功能相同,但只能与 INTERVAL 结合使用,语法结构与 ADDDATE() 的第二种形式一致。

2.3 数值处理函数

数值处理函数仅处理数值数据。这些函数一般主要用于代数、三角或几何运算,因此没有串或日期—时间处理函数的使用那么频繁。

具有讽刺意味的是,在主要DBMS的函数中,数值函数是最一致最统一的函数。

img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/75701.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

【CodeForces训练记录】Codeforces Round 981 (Div. 3)

https://codeforces.com/contest/2033 训练情况 22队长率先开出E题,但是结局可能还是掉分了 TAT赛后反思 这场太板了,D题有点反常(存疑?) A题 我们直接模拟位置的变化就行,先手 \(-2 \times i - 1\) 后手 \(+ 2 \times i - 1\),用一个while找到 \(>n\) 的地方来结束循…

东山Pi柒号-4-STM32MP157 TF-A移植

STM32MP157 TF-A 移植 在了解了 STM32MP 系列芯片的启动流程后,我们将开始进行东山 Pi 柒号的 TF-A 移植。 准备工作 首先,我们需要下载 STM32MP1 系列的 STM32MPU_Developer_Package,该包中包含编译器 SDK 和官方源码:STM32MP1 OpenSTLinux 开发套件 https://www.st.com.c…

7-1将数组中的数逆序存放

24级一维数组 题目不难,就是格式啥的要看仔细楼#include<stdio.h> int main (){int a[11] = {0};int num;int input;scanf("%d",&num);for(int i=num-1;i>=0;i--){//逆序存放!!!scanf("%d",&input);a[i] = input;}for(int i=0;i<n…

【投资理财】一起来探索金融理财世界啦

各位程序员小伙伴们,大家都知道最近大 A 股市那叫一个起伏不定啊,就像坐过山车似的,刺激得很。咱程序员平时工作忙归忙,但不少同学对炒股还挺感兴趣的,甚至有的同学在工作的时候还会偷偷摸摸瞅几眼股市行情😜。我最近发现了一些很不错的金融理财资源,想着赶紧分享给大家…

无法删除文件,因为已在Windows资源管理器中打开

背景 文件夹/文件删不掉 解决 直接重启explorer即可。 win+x,a 打开终端。 kill -name explorer按理来说关闭后explorer会自动重启 start explorer图形界面方式 Ctrl+Shift+ESC,打开任务管理器。 点击详细信息,按名称排序找到explorer.exe,右键重新启动。

学习高校课程-软件设计模式-单例模式(lec5)

原文链接 Singleton: Intent Singleton is a creational design pattern that lets you ensure that a class has only one instance, while providing a global access point to this instance. Singleton 是一种创建性设计模式,它允许您确保一个类只有一个实例,同时提供对此…

手动上传图片,怎么调整大小和居中

原始格式![image](https://img2024.cnblogs.com/blog/2143851/202410/2143851-20241024173243352-290268296.png ) 目标格式<img src="https://img2024.cnblogs.com/blog/2143851/202410/2143851-20241024173243352-290268296.png" alt="image-2024070120285…