• [技术干货] MySQL处理无效数据值
    MySQL处理数据的基本原则是“垃圾进来,垃圾出去”,通俗一点说就是你传给 MySQL 什么样的数据,它就会存储什么样的数据。如果在存储数据时没有对它们进行验证,那么在把它们检索出来时得到的就不一定是你所期望的内容。 有几种 SQL 模式可以在遇到“非正常”值时抛出错误,如果你对其他数据库管理系统比较熟悉,会发现这种行为和其他的数据库管理系统很像。 下面介绍 MySQL 默认情况下如何处理非正常数据和启用各种 SQL 模式时会对数据处理产生哪些影响。 默认情况下,MySQL 会按照以下规则来处理越界(即超出取值范围)的值和其他非正常值:对于数值列或 TIME 列,超出合法取值范围的那些值将被截断到取值范围最近的那个端点,并把结果值存储起来。对于除 TIME 列以外的其他类型列,非法值会被转换成与该类型一致的“零”值。对于字符串列(不包括 ENUM 或 SET),过长的字符串将被截断到该列的最大长度。给 ENUM 或 SET 类型列进行赋值时,需要根据列定义里给出的合法取值列表进行。如果把不是枚举成员的值赋给 ENUM 列,那么列的值就会变成空字符串。如果把包含非集合成员的子字符串的值赋给 SET 列,那么这些字符串会被清理,剩余的成员才会被赋值给列。 如果在执行增删改查等语句时发生了上述转换,那么 MySQL 会给出警告消息。在执行完其中的某一条语句之后,可以使用 SHOW WARNINGS 语句来查看警告消息的内容。 如果需要在插入或更新数据时执行更严格的检查,那么可以启用以下两种 SQL 模式中的一种:SET sql_mode = 'STRICT_ALL_TABLES' ;SET sql_mode = 'STRICT_TRANS_TABLES';对于支持事务的表,这两种模式都是一样的。如果发现某个值无效或缺失,那么会产生一个错误,并且语句会中止执行,并进行回滚,就像什么事都没发生过一样。 对于不支持事务的表,这两种模式有以下效果。 1) 对于这两种模式,如果在插入或修改第一个行时,发现某个值无效或缺失,那么结果会产生一个错误,语句会中止执行,就像什么事都未发生过一样。 这跟事务表的行为很相似。 2) 在用于插入或修改多个行的语句里,如果在第一行之后的某个行出现了错误,那么会出现某些行被修改的情况。这两种模式决定着,这条语句此时此刻是要停止执行,还是要继续执行。在 STRICT_ALL_TABLES 模式下,会抛出一个错误,并且语句会停止执行。因为受该语句影响的许多行都已被修改,所以这将会导致“部分更新”问题。在 STRICT_TRANS_TABLES 模式下,对于非事务表,MySQL 会中止语句的执行。只有这样做,才能达到事务表那样的效果。只有当第一行发生错误时,才能达到这样的效果。如果错误在后面的某个行上,那么就会出现某些行被修改的情况。由于对于非事务表,那些修改是无法撤销的,因此 MySQL 会继续执行该语句,以避免出现“部分更新”的问题。它会把所有的无效值转换为与其最接近的合法值。对于缺失的值,MySQL 会把该列设置成其数据类型的隐式默认值, 通过以下模式可以对输入的数据进行更加严格的检查:ERROR_ FOR_ DIVISION_ BY_ ZERO:在严格模式下,如果遇到以零为除数的情况,它会阻止数值进入数据库。如果不在严格模式下,则会产生一条警告消息,并插入 NULL。NO_ ZERO_ DATE:在严格模式下,它会阻止“零”日期值进入数据库。NO_ ZERO_ IN_ DATE:在严格模式下,它会阻止月或日部分为零的不完整日期值进入数据库。 简单来说,MySQL 的严格模式就是 MySQL 自身对数据进行的严格校验,例如格式、长度、类型等。比如一个整型字段我们写入一个字符串类型的数据,在非严格模式下 MySQL 不会报错。如果定义了 char 或 varchar 类型的字段,当写入或更新的数据超过了定义的长度也不会报错。 虽然我们会在代码中做数据校验,但一般认为非严格模式对于编程来说没有任何好处。MySQL开启严格模式从一定程序上来讲也是对我们代码的一种测试,如果我们没有开启严格模式并且在开发过程中也没有遇到错误,那么在上线或代码移植的时候将有可能出现不兼容的情况,因此在开发过程做最好开启 MySQL 的严格模式。 可通过select @@sql_mode;命令查看当前是严格模式还是非严格模式。 例如,如果想让所有的存储引擎启用严格模式,并对“被零除”错误进行检查,那么可以像下面这样设置 SQL 模式:SET sql_mode ‘STRICT_ALL_TABLES, ERROR_FOR_DIVISION_BY_ZERO' ; 如果想启用严格模式,以及所有的附加限制,那么最为简单的办法是启用 TRADITIONAL 模式:SET sql_ mode ‘TRADITIONAL' ;TRADITIONAL 模式的含义是“启用严格模式,当向 MySQL 数据库插入数据时,进行数据的严格校验,保证错误数据不能插入。用于事务表时,会进行事务的回滚”。 可以选择性地在某些方面弱化严格模式。如果启用了 SQL 的 ALLOW_ INVALID_ DATES 模式,那么MySQL将不会对日期部分做全面检查。相反,它只会要求月份值在 1~12 之间,而天数处于 1~31 之间,即允许像‘2000-02-30’或‘2000-06-31’这样的无效值。 另一个制止错误的办法是在 INSERT 或 UPDATE 语句里使用 IGNORE 关键字。这样那些会因无效值而导致错误的语句,将只会导致警告的出现。这些选项能让你灵活地为你的应用选择正确的有效性检查级别。
  • [技术干货] SQL中where子句与having子句的区别
    前言:Where和Having都是对查询结果的一种筛选,说的书面点就是设定条件的语句。下面这篇文章就来给大家介绍下SQL中where子句与having子句的区别,下面话不多说了,来一起看看详细的介绍吧1.where 不能放在GROUP BY 后面2.HAVING 是跟GROUP BY 连在一起用的,放在GROUP BY 后面,此时的作用相当于WHERE3.WHERE 后面的条件中不能有聚集函数,比如SUM(),AVG()等,而HAVING 可以Where和Having都是对查询结果的一种筛选,说的书面点就是设定条件的语句。下面分别说明其用法和异同点。注:本文使用字段为oracle数据库中默认用户scott下面的emp表,sal代表员工工资,deptno代表部门编号。一、聚合函数说明前我们先了解下聚合函数:聚合函数有时候也叫统计函数,它们的作用通常是对一组数据的统计,比如说求最大值,最小值,总数,平均值(MAX,MIN,COUNT, AVG)等。这些函数和其它函数的根本区别就是它们一般作用在多条记录上。简单举个例子:SELECT SUM(sal) FROM emp,这里的SUM作用是统计emp表中sal(工资)字段的总和,结果就是该查询只返回一个结果,即工资总和。通过使用GROUP BY 子句,可以让SUM 和 COUNT 这些函数对属于一组的数据起作用。二、where子句where自居仅仅用于从from子句中返回的值,from子句返回的每一行数据都会用where子句中的条件进行判断筛选。where子句中允许使用比较运算符(>,<,>=,<=,<>,!=|等)和逻辑运算符(and,or,not)。由于大家对where子句都比较熟悉,在此不在赘述。三、having子句having子句通常是与order by 子句一起使用的。因为having的作用是对使用group by进行分组统计后的结果进行进一步的筛选。举个例子:现在需要找到部门工资总和大于10000的部门编号?第一步:select deptno,sum(sal) from emp group by deptno;筛选结果如下:DEPTNO SUM(SAL) —— ———- 30 9400 20 10875 10 8750可以看出我们想要的结果了。不过现在我们如果想要部门工资总和大于10000的呢?那么想到了对分组统计结果进行筛选的having来帮我们完成。第二步:select deptno,sum(sal) from emp group by deptno having sum(sal)>10000;筛选结果如下:DEPTNO SUM(SAL) —— ———- 20 10875当然这个结果正是我们想要的。四、下面我们通过where子句和having子句的对比,更进一步的理解它们。在查询过程中聚合语句(sum,min,max,avg,count)要比having子句优先执行,简单的理解为只有有了统计结果后我才能执行筛选。where子句在查询过程中执行优先级别优先于聚合语句(sum,min,max,avg,count),因为它是一句一句筛选的。HAVING子句可以让我们筛选成组后的对各组数据筛选。,而WHERE子句在聚合前先筛选记录。如:现在我们想要部门号不等于10的部门并且工资总和大于8000的部门编号?我们这样分析:通过where子句筛选出部门编号不为10的部门,然后在对部门工资进行统计,然后再使用having子句对统计结果进行筛选。select deptno,sum(sal) from emp  where deptno!='10' group by deptno having sum(sal)>8000;筛选结果如下:DEPTNO SUM(SAL) —— ———- 30 9400 20 10875五、异同点它们的相似之处就是定义搜索条件,不同之处是where子句为单个筛选而having子句与组有关,而不是与单个的行有关。最后:理解having子句和where子句最好的方法就是基础select语句中的那些句子的处理次序:where子句只能接收from子句输出的数据,而having子句则可以接受来自group by,where或者from子句的输入。
  • [技术干货] SQL语句执行顺序
    开发对于数据的存储,应用的常用在技术的不断提高,使用的范围和问题就不断的出现。由于SQL 不同于与其他编程语言的最明显特征是处理代码的顺序。在大数编程语言中,代码按编码顺序被处理,但是在SQL语言中,第一个被处理的子句是FROM子句,尽管SELECT语句第一个出现,但是几乎总是最后被处理。      每个步骤都会产生一个虚拟表,该虚拟表被用作下一个步骤的输入。这些虚拟表对调用者(客户端应用程序或者外部查询)不可用。只是最后一步生成的表才会返回 给调用者。如果没有在查询中指定某一子句,将跳过相应的步骤。下面是对应用于SQL server 2000和SQL Server 2005的各个逻辑步骤的简单描述。(8)SELECT (9)DISTINCT (11)<Top Num> <select list> (1)FROM [left_table] (3)<join_type> JOIN <right_table> (2)ON <join_condition> (4)WHERE <where_condition> (5)GROUP BY <group_by_list> (6)WITH <CUBE | RollUP> (7)HAVING <having_condition> (10)ORDER BY <order_by_list>逻辑查询处理阶段简介FROM:对FROM子句中的前两个表执行笛卡尔积(Cartesian product)(交叉联接),生成虚拟表VT1ON:对VT1应用ON筛选器。只有那些使<join_condition>为真的行才**入VT2。OUTER(JOIN):如 果指定了OUTER JOIN(相对于CROSS JOIN 或(INNER JOIN),保留表(preserved table:左外部联接把左表标记为保留表,右外部联接把右表标记为保留表,完全外部联接把两个表都标记为保留表)中未找到匹配的行将作为外部行添加到 VT2,生成VT3.如果FROM子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到处理完所有的表为止。WHERE:对VT3应用WHERE筛选器。只有使<where_condition>为true的行才**入VT4.GROUP BY:按GROUP BY子句中的列列表对VT4中的行分组,生成VT5.CUBE|ROLLUP:把超组(Suppergroups)插入VT5,生成VT6.HAVING:对VT6应用HAVING筛选器。只有使<having_condition>为true的组才会**入VT7.SELECT:处理SELECT列表,产生VT8.DISTINCT:将重复的行从VT8中移除,产生VT9.ORDER BY:将VT9中的行按ORDER BY 子句中的列列表排序,生成游标(VC10).TOP:从VC10的开始处选择指定数量或比例的行,生成表VT11,并返回调用者。按ORDER BY子句中的列列表排序上步返回的行,返回游标VC10.这一步是第一步也是唯一一步可以使用SELECT列表中的列别名的步骤。这一步不同于其它步骤的 是,它不返回有效的表,而是返回一个游标。SQL是基于集合理论的。集合不会预先对它的行排序,它只是成员的逻辑集合,成员的顺序无关紧要。对表进行排序 的查询可以返回一个对象,包含按特定物理顺序组织的行。ANSI把这种对象称为游标。理解这一步是正确理解SQL的基础。因为这一步不返回表(而是返回游标),使用了ORDER BY子句的查询不能用作表表达式。表表达式包括:视图、内联表值函数、子查询、派生表和共用表达式。它的结果必须返回给期望得到物理记录的客户端应用程序。例如,下面的派生表查询无效,并产生一个错误:select *  from(select orderid,customerid from orders order by orderid)  as d下面的视图也会产生错误create view my_view as select * from orders order by orderid在SQL中,表表达式中不允许使用带有ORDER BY子句的查询,而在T—SQL中却有一个例外(应用TOP选项)。      所以记住,不要为表中的行假设任何特定的顺序。换句话说,除非你确定要有序行,否则不要指定ORDER BY 子句。排序是需要成本的,SQL Server需要执行有序索引扫描或使用排序运行符。
  • [技术干货] sql server中判断表或临时表是否存在的方法
    1、判断数据表是否存在方法一:use yourdb; go if object_id(N'tablename',N'U') is not null print '存在' else  print '不存在'例子use fireweb; go if object_id(N'TEMP_TBL',N'U') is not null print '存在' else  print '不存在'方法二:USE [实例名]  GO  IF EXISTS (SELECT * FROM dbo.SysObjects WHERE ID = object_id(N'[表名]') AND OBJECTPROPERTY(ID, 'IsTable') = 1)  PRINT '存在'  ELSE  PRINT'不存在'例子:use fireweb; go IF EXISTS (SELECT * FROM dbo.SysObjects WHERE ID = object_id(N'TEMP_TBL') AND OBJECTPROPERTY(ID, 'IsTable') = 1)  PRINT '存在'  ELSE  PRINT'不存在'2、临时表是否存在:方法一:use fireweb; go if exists(select * from tempdb..sysobjects where id=object_id('tempdb..##TEMP_TBL')) PRINT '存在'  ELSE  PRINT'不存在'方法二:use fireweb; go if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..#TEMP_TBL') and type='U') PRINT '存在'  ELSE  PRINT'不存在'补充介绍:在sqlserver(应该说在目前所有数据库产品)中创建一个资源如表,视图,存储过程中都要判断与创建的资源是否已经存在在sqlserver中一般可通过查询sys.objects系统表来得知结果,不过可以有更方便的方法如下:  if  object_id('tb_table') is not null      print 'exist'    else      print'not exist'如上,可用object_id()来快速达到相同的目的,tb_table就是我将要创建的资源的名称,所以要先判断当前数据库中不存在相同的资源object_id()可接受两个参数,第一个如上所示,代表资源的名称,上面的就是表的名字,但往往我们要说明我们所要创建的是什么类型的资源,这样sql可以明确地在一种类型的资源中查找是否有重复的名字,如下:  if  object_id('tb_table','u') is not null      print 'exist'    else      print'not exist'第二个参数 "u" 就表示tb_table是用户创建的表,即:USER_TABLE地首字母简写查询sys.objects中可得到各种资源的类型名称(TYPE列),这里之举几个主要的例子u ----------- 用户创建的表,区别于系统表(USER_TABLE)s ----------- 系统表(SYSTEM_TABLE)v ----------- 视图(VIEW)p ----------- 存储过程(SQL_STORED_PROCEDURE)可使用select distinct type ,type_desc from sys.objects 获得全部信息库是否存在if exists(select * from master..sysdatabases where name=N'库名')  print 'exists' else print 'not exists' ---------------  -- 判断要创建的表名是否存在  if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[表名]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)  -- 删除表  drop table [dbo].[表名]  GO  ---------------  -----列是否存在  IF COL_LENGTH( '表名','列名') IS NULL PRINT 'not exists' ELSE PRINT 'exists' alter table 表名 drop constraint 默认值名称  go  alter table 表名 drop column 列名  go  -----  --判断要创建临时表是否存在  If Object_Id('Tempdb.dbo.#Test') Is Not Null Begin print '存在' End Else Begin print '不存在' End ---------------  -- 判断要创建的存储过程名是否存在  if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[存储过程名]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)  -- 删除存储过程  drop procedure [dbo].[存储过程名]  GO  ---------------  -- 判断要创建的视图名是否存在  if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[视图名]') and OBJECTPROPERTY(id, N'IsView') = 1)  -- 删除视图  drop view [dbo].[视图名]  GO  ---------------  -- 判断要创建的函数名是否存在  if exists (select * from sysobjects where xtype='fn' and name='函数名')  if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[函数名]') and xtype in (N'FN', N'IF', N'TF'))  -- 删除函数  drop function [dbo].[函数名]  GO  if col_length('表名', '列名') is null print '不存在' select 1 from sysobjects where id in (select id from syscolumns where name='列名') and name='表名'
  • [技术干货] 安全地关闭MySQL
    停止复制在一些特殊环境下,slave节点可能会尝试从错误的位置(position)进行启动。为了减少这种风险,要先停止io thread,从而不接收新的事件信息。mysql> stop slave io_thread;等sql thread应用完所有的events之后,也将sql thread停掉。‘mysql> show slave status\G mysql> stop slave sql_thread;这样io thread和sql thread就可以处于一致性位置,这样relay log就只是包含被执行过的events,relay_log_info_repository中的位置信息也是最新的。对于开启了多线程复制的slave,确保在关闭复制之前,已经填充了gapsmysql> stop slave; mysql> start slave until sql_after_mts_gaps; #应用完relay log中的gap mysql> show slave status\G #要确保在之前已经停掉了sql_thread mysql> stop slave ;提交、回滚kill长时间运行的事务1分钟内可以发生很多事,在关闭时,innodb必须回滚未提交的事务。事务回滚的代价是非常昂贵的,可能会花费很长时间。任何事务回滚都可能意味着数据丢失,因此理想情况下关闭时没有打开任何事务。如果关闭的是读写的数据库,写操作应该提前路由到其他节点。如果必须关闭还在接收事务的数据库,下面的查询会输出运行时间大于60秒的会话信息。根据这些信息再决定下一步:mysql> SELECT trx_id, trx_started, (NOW() - trx_started) trx_duration_seconds, id processlist_id, user, IF(LEFT(HOST, (LOCATE(':', host) - 1)) = '', host, LEFT(HOST, (LOCATE(':', host) - 1))) host, command, time, REPLACE(SUBSTRING(info,1,25),'\n','') info_25 FROM information_schema.innodb_trx JOIN information_schema.processlist ON innodb_trx.trx_mysql_thread_id = processlist.id WHERE (NOW() - trx_started) > 60 ORDER BY trx_started; +--------+---------------------+----------------------+----------------+------+-----------+---------+------+---------------------------+ | trx_id | trx_started         | trx_duration_seconds | processlist_id | user | host      | command | time | info_25                   | +--------+---------------------+----------------------+----------------+------+-----------+---------+------+---------------------------+ | 511239 | 2020-04-22 16:52:23 |                 2754 |           3515 | dba  | localhost | Sleep   | 1101 | NULL                      | | 511240 | 2020-04-22 16:53:44 |                   74 |           3553 | root | localhost | Query   |   38 | update t1 set name="test" | +--------+---------------------+----------------------+----------------+------+-----------+---------+------+---------------------------+ 2 rows in set (0.00 sec)3.清空processlistmysql要断开连接并关闭了。我们可以手动帮助mysql一下。使用pt-kill查看并杀死活跃和睡眠状态的连接。这时应该不会有新的写连接进来。我们只是处理读的连接。pt-kill --host="localhost" --victims="all" --interval=10 --ignore-user="pmm|orchestrator" --busy-time=1 --idle-time=1 --print [--kill]这里可以选择性地排除某些用户建立的连接。4.配置innodb完成最大刷新(flush)SET GLOBAL innodb_fast_shutdown=0; SET GLOBAL innodb_max_dirty_pages_pct=0; SET GLOBAL innodb_change_buffering='none';disable掉innodb_fast_shutdown可能会使得关闭过程花费几分钟甚至个把小时,因为需要等待undo log的purge和changebuffer的merge。为了加速关闭,设置innodb_max_dirty_pages_pct=0并监控下面查询的结果。期望值是0,但并不总是能保证,如果mysql中还有活动的话。那么,查出的结果不再继续变小的话,就可以继续下一步了:SHOW GLOBAL STATUS LIKE '%dirty%';如果使用了pmm监控,可以查看“innodb change buffer”的图示5.转储buffer pool中的内容SET GLOBAL innodb_buffer_pool_dump_pct=75; SET GLOBAL innodb_buffer_pool_dump_now=ON;mysql> SHOW STATUS LIKE 'Innodb_buffer_pool_dump_status'; +--------------------------------+--------------------------------------------------+ | Variable_name                  | Value                                            | +--------------------------------+--------------------------------------------------+ | Innodb_buffer_pool_dump_status | Buffer pool(s) dump completed at 200429 14:04:47 | +--------------------------------+--------------------------------------------------+ 1 row in set (0.01 sec)启动的时候,要想加载转储出的内容,要检查一下参数innodb_buffer_pool_load_at_startup的配置。6.刷日志FLUSH LOGS;现在,就可以关闭mysql了。大多时候,我们只是执行stop命令,MySQL关闭并重启都是很正常的。偶尔也会遇到一些问题。
  • [技术干货] 数据库涉及到哪些技术?
    数据库系统由硬件和软件共同构成,硬件主要用于存储数据库中的数据,包括计算机、存储设备等。软件部分则主要包括 DBMS、支持 DBMS 运行的操作系统,以及支持多种语言进行应用开发的访问技术等。通过学习一段时间的华为云数据库课程,简要的说一说数据库涉及到的技术,包括数据库系统、SQL 语言和数据库访问接口。数据库系统数据库系统主要有以下 3 个组成部分:数据库:用于存储数据的地方。数据库管理系统:用于管理数据库的软件。数据库应用程序:为了提高数据库系统的处理能力所使用的管理数据库库的软件补充。数据库管理系统(Database Management System,DBMS)是位于操作系统与用户之间的一种操纵和管理数据库的软件,按照一定的数据模型科学地组织和存储数据,同时可以提供数据高效地获取和维护。数据库管理系统的主要功能包括以下几个方面。1) 数据定义功能DBMS 提供数据定义语言(Data Definition Language,DDL),用户通过它可以方便地对数据库中的数据对象进行定义。2) 数据操纵功能DBMS 还提供数据操纵语言(Data Manipulation Language,DML),用户可以使用 DML 操作数据,实现对数据库的基本操作,如查询、插入、删除和修改等。3) 数据库的运行管理数据库在建立、运用和维护时由数据库管理系统统一管理、统一控制,以保证数据的安全性、完整性、多用户对数据的并发使用及发生故障后的系统恢复。例如:数据的完整性检查功能保证用户输入的数据应满足相应的约束条件;数据库的安全保护功能保证只有赋予权限的用户才能访问数据库中的数据;数据库的并发控制功能使多个用户可以在同一时刻并发地访问数据库的数据;数据库系统的故障恢复功能使数据库运行出现故障时可以进行数据库恢复,以保证数据库可靠地运行。4) 提供方便、有效地存取数据库信息的接口和工具编程人员可通过编程语言与数据库之间的接口进行数据库应用程序的开发。数据库管理员(Database Administrator,DBA)可通过提供的工具对数据库进行管理。数据库管理员是维护和管理数据库的专门人员。5) 数据库的建立和维护功能数据库功能包括数据库初始数据的输入、转换功能,数据库的转储、恢复功能,数据库的重组织功能和性能监控、分析功能等。这些功能通常由一些使用程序来完成。数据库系统是指在计算机系统中引入数据库后的系统。一个完整的数据库系统(Database System,DBS)一般由数据库、数据库管理系统、应用开发工具、应用系统、数据库管理员和用户组成。完整的数据库系统结构关系如图所示:了解SQL语言MySQL 服务器正确安装以后,就已经完成了一个完整的 DBMS 的搭建,可以通过命令行管理工具或者图形化的管理工具对 MySQL 数据库进行操作。这种对数据库进行查询和修改操作的语言叫做 SQL(Structured Query Language,结构化查询语言)。SQL 语言是目前广泛使用的关系数据库标准语言,是各种数据库交互方式的基础。SQL 是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。与其他程序设计语言(如 C语言、Java 等)不同的是,SQL 由很少的关键字组成,每个 SQL 语句通过一个或多个关键字构成。SQL 具有如下优点。一体化:SQL 集数据定义、数据操作和数据控制于一体,可以完成数据库中的全部工作。使用方式灵活:SQL 具有两种使用方式,可以直接以命令方式交互使用;也可以嵌入使用,嵌入C、C++、Fortran、COBOL、Java 等语言中使用。非过程化:只提操作要求,不必描述操作步骤,也不需要导航。使用时只需要告诉计算机“做什么”,而不需要告诉它“怎么做”,存储路径的选择和操作的执行由数据库管理系统自动完成。语言简洁、语法简单:该语言的语句都是由描述性很强的英语单词组成,而且这些单词的数目不多。SQL 包含以下 4 部分:数据定义语言(DDL):DROP、CREATE、ALTER 等语句。数据操作语言(DML):INSERT(插入)、UPDATE(修改)、DELETE(删除)语句。数据查询语言(DQL):SELECT 语句。数据控制语言(DCL): GRANT、REVOKE、COMMIT、ROLLBACK 等语句。下面是一条 SQL 语句的例子,该语句声明创建一个名叫 students 的表:CREATE TABLE students (     student_id INT UNSIGNED,     name VARCHAR(30) ,     sex CHAR(1),     birth DATE,     PRIMARY KEY(student_id) );该表包含 4 个字段,分别为 student_id、name、sex、birth,其中 student_id 定义为表的主键。现在只是定义了一张表格,但并没有任何数据,接下来这条 SQL 声明语句,将在 students 表中插入一条数据记录:INSERT INTO students (student_id, name, sex, birth) VALUES (888, '华为云MySQL教程', '1', '2020-12-17');执行完该 SQL 语句之后,students 表中就会增加一行新记录,该记录中字段 student_id 的值为“888”,name 字段的值为“华为云MySQL教程”。sex 字段值为“1”,birth 字段值为“2020-12-17”。再使用 SELECT 查询语句获取刚才插入的数据,如下:SELECT name FROM students WHERE student_id=888; +--------------+ | name         | +--------------+ |华为云MySQL教程| +--------------+上面简单列举了常用的数据库操作语句,在这里留下一个印象即可,后面我们会详细介绍这些知识。注意:SQL 语句不区分大小写,许多 SQL 开发人员习惯对 SQL 本身的关键字进行大写,而对表或者列的名称使用小写,这样可以提高代码的可阅读性和可维护性。本教程也按照这种方式组织 SQL 语句。大多数数据库都支持通用的 SQL 语句,同时不同的数据库具有各自特有的 SQL 语言特性。数据库访问接口不同的程序设计语言会有各自不同的数据库访问接口,程序语言通过这些接口,执行 SQL 语句,进行数据库管理。主要的数据库访问接口主要有  ODBC、JDBC、ADO.NET 和 PDO。ODBCODBC(Open Database Connectivity,开放数据库互连)为访问不同的 SQL 数据库提供了一个共同的接口。ODBC 使用 SQL 作为访问数据的标准。这一接口提供了最大限度的互操作性。一个应用程序可以通过共同的一组代码访问不同的 SQL 数据库管理系统。一个基于 ODBC 的应用程序对数据库的操作不依赖任何 DBMS,不直接与 DBMS 打交道,所有的数据库操作由对应的 DBMS 的 ODBC 驱动程序完成。也就是说,不论是 MySQL 还是 Oracle 数据库,均可用 ODBC API 进行访问。由此可见,ODBC 的最大优点是能以统一的方式处理所有的数据库。JDBCJava Data Base(JDBC,Java 数据库连接)用于 Java 应用程序连接数据库的标准方法,是一种用于执行 SQL 语句的 Java API,可以为多种关系数据库提供统一访问,它由一组用 Java 语言编写的类和接口组成。ADO.NETADO.NET 是微软在 .NET 框架下开发设计的一组用于和数据源进行交互的面向对象类库。ADO.NET 提供了对关系数据、XML 和应用程序的访问,允许和不同类型的数据源以及数据库进行交互。PDOPDO(PHP Data Object)为 PHP 访问数据库定义了一个轻量级的、一致性的接口,它提供了一个数据访问抽象层,这样,无论使用什么数据库,都可以通过一致的函数执行查询和获取数据。PDO 是 PHP 5 新加入的一个重大功能。
  • [技术干货] SQL server分页的4种方法示例
    一下为SQL server 2012版本。下面都用pageIndex表示页数,pageSize表示一页包含的记录。并且下面涉及到具体例子的,设定查询第2页,每页含10条记录。首先说一下SQL server的分页与MySQL的分页的不同,mysql的分页直接是用limit (pageIndex-1),pageSize就可以完成,但是SQL server 并没有limit关键字,只有类似limit的top关键字。所以分页起来比较麻烦。SQL server分页我所知道的就只有四种:三重循环;利用max(主键);利用row_number关键字,offset/fetch next关键字(是通过搜集网上的其他人的方法总结的,应该目前只有这四种方法的思路,其他方法都是基于此变形的)。要查询的学生表的部分记录方法一:三重循环 思路先取前20页,然后倒序,取倒序后前10条记录,这样就能得到分页所需要的数据,不过顺序反了,之后可以将再倒序回来,也可以不再排序了,直接交给前端排序。还有一种方法也算是属于这种类型的,这里就不放代码出来了,只讲一下思路,就是先查询出前10条记录,然后用not in排除了这10条,再查询。代码实现-- 设置执行时间开始,用来查看性能的 set statistics time on ; -- 分页查询(通用型) select *  from (select top pageSize *  from (select top (pageIndex*pageSize) *  from student  order by sNo asc ) -- 其中里面这层,必须指定按照升序排序,省略的话,查询出的结果是错误的。 as temp_sum_student  order by sNo desc ) temp_order order by sNo asc -- 分页查询第2页,每页有10条记录 select *  from (select top 10 *  from (select top 20 *  from student  order by sNo asc ) -- 其中里面这层,必须指定按照升序排序,省略的话,查询出的结果是错误的。 as temp_sum_student  order by sNo desc ) temp_order order by sNo asc ;查询出的结果及时间方法二:利用max(主键)先top前11条行记录,然后利用max(id)得到最大的id,之后再重新再这个表查询前10条,不过要加上条件,where id>max(id)。代码实现set statistics time on; -- 分页查询(通用型) select top pageSize *  from student  where sNo>= (select max(sNo)  from (select top ((pageIndex-1)*pageSize+1) sNo from student  order by sNo asc) temp_max_ids)  order by sNo; -- 分页查询第2页,每页有10条记录 select top 10 *  from student  where sNo>= (select max(sNo)  from (select top 11 sNo from student  order by sNo asc) temp_max_ids)  order by sNo;查询出的结果及时间方法三:利用row_number关键字直接利用 row_number() over(order by id) 函数计算出行数,选定相应行数返回即可,不过该关键字只有在SQL server 2005版本以上才有。SQL实现set statistics time on; -- 分页查询(通用型) select top pageSize *  from (select row_number()  over(order by sno asc) as rownumber,*  from student) temp_row where rownumber>((pageIndex-1)*pageSize); set statistics time on; -- 分页查询第2页,每页有10条记录 select top 10 *  from (select row_number()  over(order by sno asc) as rownumber,*  from student) temp_row where rownumber>10;查询出的结果及时间第四种方法:offset /fetch next(2012版本及以上才有)代码实现set statistics time on; -- 分页查询(通用型) select * from student order by sno  offset ((@pageIndex-1)*@pageSize) rows fetch next @pageSize rows only; -- 分页查询第2页,每页有10条记录 select * from student order by sno  offset 10 rows fetch next 10 rows only ;offset A rows ,将前A条记录舍去,fetch next B rows only ,向后在读取B条数据。结果及运行时间封装的存储过程最后,我封装了一个分页的存储过程,方便大家调用,这样到时候写分页的时候,直接调用这个存储过程就可以了。分页的存储过程create procedure paging_procedure ( @pageIndex int, -- 第几页 @pageSize int -- 每页包含的记录数 ) as begin  select top (select @pageSize) *   -- 这里注意一下,不能直接把变量放在这里,要用select from (select row_number() over(order by sno) as rownumber,*  from student) temp_row  where rownumber>(@pageIndex-1)*@pageSize; end -- 到时候直接调用就可以了,执行如下的语句进行调用分页的存储过程 exec paging_procedure @pageIndex=2,@pageSize=10;
  • [技术干货] Mysql跨表更新 多表update sql语句总结
    假定我们有两张表,一张表为Product表存放产品信息,其中有产品价格列Price;另外一张表是ProductPrice表,我们要将ProductPrice表中的价格字段Price更新为Price表中价格字段的80%。在Mysql中我们有几种手段可以做到这一点,一种是update table1 t1, table2 ts ...的方式:  UPDATE product p, productPrice pp  SET pp.price = pp.price * 0.8  WHERE p.productId = pp.productId  AND p.dateCreated < '2004-01-01'另外一种方法是使用inner join然后更新:  UPDATE product p  INNER JOIN productPrice pp  ON p.productId = pp.productId  SET pp.price = pp.price * 0.8  WHERE p.dateCreated < '2004-01-01'另外我们也可以使用left outer join来做多表update,比方说如果ProductPrice表中没有产品价格记录的话,将Product表的isDeleted字段置为1,如下sql语句:  UPDATE product p  LEFT JOIN productPrice pp  ON p.productId = pp.productId  SET p.deleted = 1  WHERE pp.productId IS null另外,上面的几个例子都是两张表之间做关联,但是只更新一张表中的记录,其实是可以同时更新两张表的,如下sql:  UPDATE product p  INNER JOIN productPrice pp  ON p.productId = pp.productId  SET pp.price = pp.price * 0.8,  p.dateUpdate = CURDATE()  WHERE p.dateCreated < '2004-01-01'
  • [技术干货] 将SQL语句映射为文件操作
    1. 查询数据表前面介绍过,在 MySQL 中无论哪种存储引擎的表都会有一个 .frm 文件来保存数据表的结构定义。所以,执行 SHOW TABLES; 语句相当于列出数据库目录中所有 .frm 文件的基本名,所得到的结果是相同的。有些数据库系统使用注册表来记录某数据库里的所有数据表,但 MySQL 没有这样做,因为,MySQL 数据目录的层次结构已经把“注册表”隐藏在其中了。2. 创建数据表创建数据表时,需要执行 CREATE TABLE 语句定义数据表的结构。无论是哪一种存储引擎,MySQL 服务器都将创建一个 .frm 文件来保存数据表的结构定义的内部编码。MySQL 服务器还会根据指定数据表的具体类型创建出其他必要的文件。例如,它将为一个 MyISAM 数据表创建出一个 .MYD 数据文件和一个 .MYI 索引文件;为一个 MERGE 数据表创建出一个 .mgr 数据/索引文件。对于 InnoDB 数据表,InnoDB 处理程序将在 InnoDB 表空间里为数据表初始化一些数据和索引信息。3. 更新数据表当执行 ALTER TABLE 语句时,MySQL 服务器将对相对应数据表的 .frm 文件重新进行编码,来表明数据表的结构性变化,还要对有关的数据文件和索引文件的内容进行相应的修改。CREATE INDEX 和 DROP INDEX 等语句也是对相应数据表的 .frm 文件重新进行编码,因为 MySQL 服务器在内部是把它们当作等效的 ALTER TABLE 语句来处理的。改变 InnoDB 数据表的结构会引起 InnoDB 处理程序修改 InnoDB 表空间中数据表的数据,同时也对索引做出相应的修改。4. 删除数据表DROP TABLE 语句是通过删除该相应数据表的各种有关文件而实现的。对于某些数据表类型,可以通过在相应的数据库目录里删除与数据表有关的各个文件的办法来手动删除这个数据表。例如,假设 mydb 是当前数据库,mytb1 是一个 MyISAM、Archive 或 MERGE 类型的数据表,那么 DROP TABLE mytb1 语句就大致等效于下面这两条命令:cd DATADIR(数据库文件存放路径)rm -f mydb/mytb1.* 或 del mydb/mytb1.*对于 InnoDB 数据表,因为它的某些组成部分在文件系统里没有实体性的文件代表,所以没有等效的文件系统命令。例如,InnoDB 数据表在文件系统里只有一个相应的 .frm 文件,用文件系统级命令删除这个文件后,该数据表在 InnoDB 表空间中对应的数据和索引将没有任何意义。
  • [系统培训] 【培训回顾汇总】华为云数仓GaussDB(DWS) 培训视频汇总
    本贴汇总了华为云数仓GaussDB(DWS)培训系列课程及直播回顾链接,欢迎大家围观,共同交流学习,学习材料见附件,文末有福利哦~:您也可以留言您想学习/了解的课程,后续有机会成为直播课程主题哦·~·培训主题培训简介直播时间回顾链接GaussDB(DWS)产品介绍本讲是第一场,聚焦介绍GaussDB(DWS)应用场景、关键特性与案例介绍、典型配置,让您初步了解GaussDB(DWS)是啥,有啥特性,有哪些成功案例等。2020年8月31日   14:00~17:30cid:link_6GaussDB(DWS)集群部署与管理本讲为您介绍华为云数仓GaussDB(DWS)集群网络规划,集群部署,部署完后的管理界面FI的基本功能,包括节点替换,扩容等。cid:link_7GaussDB(DWS) 数据库对象设计本讲从GaussDB(DWS)   数据库整体设计,对象命名规范,对象设计原则,Sql编写规则四个方面详细讲解了应用层如何用好数据仓库GaussDB(DWS) 2020年9月1日   14:00~18:00cid:link_8GaussDB(DWS) 数据迁移本讲主要讲述通过GDS和COPY工具进行物理数据的迁移,通过gs_dump/gs_resotre迁移元   数据,以及介绍GaussDB(DWS)的ETL工具,对Migration工具的使用简单说明。 cid:link_9GaussDB(DWS) SQL进阶及应用开发指南本讲分两部分,第一部分Sql进阶,详细讲解了GaussDB(DWS)的数据字典,数据类型,函数操作符,存储过程等,第二部分应用程序应用指南,从数据库驱动概念,基于ODBC/JDBC的应用程序开发。cid:link_10GaussDB(DWS)事务、锁机制管理本讲为您介绍华为云数仓GaussDB(DWS)   单机事务机制,分布式事务机制,锁机制,并介绍一般的锁问题定位防范,例如死锁问题。 2020年9月2日   14:00~18:00cid:link_11GaussDB(DWS)资源负载管理本讲为您介绍华为云数仓GaussDB(DWS)   多租户机制,资源管理及负载管理机制,让您了解多租户的基本概念及基本设置方法,了解资源负载的基本原理及并发管理机制,初步进行资源负载分析和配置cid:link_12GaussDB(DWS)性能调优本讲为您介绍华为云数仓GaussDB(DWS)   调优的基本理论、常见的SQL性能问题的定位手段和解决方案 cid:link_13GaussDB(DWS)安全与权限设计本讲围绕华为云数仓GaussDB(DWS)   数据安全的核心问题:谁能看?能看啥?看没看?依托分布式架构,逐层为您解答,透明加密,数据加密,三权分立,行列及控制,用户管理,私有用户等概念 cid:link_14GaussDB(DWS) 补丁、升级及扩容流程本讲主要介绍GaussDB(DWS)如何打补丁,升级及扩容,有哪些注意事项等。2020年9月3日   19:00~21:00cid:link_15GaussDB(DWS) 备份与恢复本讲主要讲了GaussDB(DWS)   的备份恢复工具Roach,介绍了其运作原理,操作命令,注意事项等。cid:link_16GaussDB(DWS) 日常巡检本讲介绍GaussDB(DWS)   日常巡检。 2020年9月4日   14:00~16:30cid:link_17GaussDB(DWS) 常见问题三板斧本讲为您总结了华为云数仓GaussDB(DWS)在集群,sql,内存方面的常见问题的定位思路及实际操作演练cid:link_18【推荐阅读】【最新活动汇总】DWS活动火热进行中,互动好礼送不停(持续更新中)  HOT  【博文汇总】GaussDB(DWS)博文汇总1,欢迎大家交流探讨~(持续更新中)【维护宝典汇总】GaussDB(DWS)维护宝典汇总贴1,欢迎大家交流探讨(持续更新中)【项目实践汇总】GaussDB(DWS)项目实践汇总贴,欢迎大家交流探讨(持续更新中)【DevRun直播汇总】GaussDB(DWS)黑科技直播汇总,欢迎大家交流学习(持续更新中)【培训视频汇总】GaussDB(DWS) 培训视频汇总,欢迎大家交流学习(持续更新中)扫码关注我哦,我在这里↓↓↓
  • [技术干货] MySQL ALTER命令
    当我们需要修改数据表名或者修改数据表字段时,就需要使用到MySQL ALTER命令。开始介绍ALTER前让我们先创建一张表,表名为:testalter_tbl。root@host# mysql -u root -p password;Enter password:*******mysql> use RUNOOB;Database changed mysql> create table testalter_tbl    -> (     -> i INT,     -> c CHAR(1)     -> );Query OK, 0 rows affected (0.05 sec)mysql> SHOW COLUMNS FROM testalter_tbl;     +-------+---------+------+-----+---------+-------+     | Field | Type    | Null | Key | Default | Extra      |+-------+---------+------+-----+---------+-------+     | i     | int(11) | YES  |     | NULL    |  |     | c     | char(1) | YES  |     | NULL    |  |     +-------+---------+------+-----+---------+-------+      2rows in set (0.00 sec)删除,添加或修改表字段如下命令使用了 ALTER 命令及 DROP 子句来删除以上创建表的 i 字段:mysql> ALTER TABLE testalter_tbl  DROP i;如果数据表中只剩余一个字段则无法使用DROP来删除字段。MySQL 中使用 ADD 子句来向数据表中添加列,如下实例在表 testalter_tbl 中添加 i 字段,并定义数据类型:mysql> ALTER TABLE testalter_tbl ADD i INT;执行以上命令后,i 字段会自动添加到数据表字段的末尾。mysql> SHOW COLUMNS FROM testalter_tbl; +-------+---------+------+-----+---------+-------+ | Field | Type    | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | c     | char(1) | YES  |     | NULL    |  | | i     | int(11) | YES  |     | NULL    |  | +-------+---------+------+-----+---------+-------+ 2 rows in set (0.00 sec)如果你需要指定新增字段的位置,可以使用MySQL提供的关键字 FIRST (设定位第一列), AFTER 字段名(设定位于某个字段之后)。尝试以下 ALTER TABLE 语句, 在执行成功后,使用 SHOW COLUMNS 查看表结构的变化:ALTER TABLE testalter_tbl DROP i; ALTER TABLE testalter_tbl ADD i INT FIRST; ALTER TABLE testalter_tbl DROP i; ALTER TABLE testalter_tbl ADD i INT AFTER c;FIRST 和 AFTER 关键字可用于 ADD 与 MODIFY 子句,所以如果你想重置数据表字段的位置就需要先使用 DROP 删除字段然后使用 ADD 来添加字段并设置位置。修改字段类型及名称如果需要修改字段类型及名称, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句 。例如,把字段 c 的类型从 CHAR(1) 改为 CHAR(10),可以执行以下命令:mysql> ALTER TABLE testalter_tbl MODIFY c CHAR(10);使用 CHANGE 子句, 语法有很大的不同。 在 CHANGE 关键字之后,紧跟着的是你要修改的字段名,然后指定新字段名及类型。尝试如下实例:mysql> ALTER TABLE testalter_tbl CHANGE i j BIGINT;<p如果你现在想把字段 j="" 从="" bigint="" 修改为="" int,sql语句如下:mysql> ALTER TABLE testalter_tbl CHANGE j j INT;ALTER TABLE 对 Null 值和默认值的影响当你修改字段时,你可以指定是否包含值或者是否设置默认值。以下实例,指定字段 j 为 NOT NULL 且默认值为100 。mysql> ALTER TABLE testalter_tbl      -> MODIFY j BIGINT NOT NULL DEFAULT 100;如果你不设置默认值,MySQL会自动设置该字段默认为 NULL。修改字段默认值你可以使用 ALTER 来修改字段的默认值,尝试以下实例:mysql> ALTER TABLE testalter_tbl ALTER i SET DEFAULT 1000; mysql> SHOW COLUMNS FROM testalter_tbl; +-------+---------+------+-----+---------+-------+ | Field | Type    | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | c     | char(1) | YES  |     | NULL    |  | | i     | int(11) | YES  |     | 1000    |  | +-------+---------+------+-----+---------+-------+ 2 rows in set (0.00 sec)你也可以使用 ALTER 命令及 DROP子句来删除字段的默认值,如下实例:mysql> ALTER TABLE testalter_tbl ALTER i DROP DEFAULT; mysql> SHOW COLUMNS FROM testalter_tbl; +-------+---------+------+-----+---------+-------+ | Field | Type    | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | c     | char(1) | YES  |     | NULL    |  | | i     | int(11) | YES  |     | NULL    |  | +-------+---------+------+-----+---------+-------+ 2 rows in set (0.00 sec)Changing a Table Type:修改数据表类型,可以使用 ALTER 命令及 TYPE 子句来完成。尝试以下实例,我们将表 testalter_tbl 的类型修改为 MYISAM :注意:查看数据表类型可以使用 SHOW TABLE STATUS 语句。mysql> ALTER TABLE testalter_tbl ENGINE = MYISAM;mysql>  SHOW TABLE STATUS LIKE 'testalter_tbl'\G*************************** 1. row ****************            Name: testalter_tbl           Type: MyISAM      Row_format: Fixed            Rows: 0  Avg_row_length: 0     Data_length: 0Max_data_length: 25769803775    Index_length: 1024       Data_free: 0  Auto_increment: NULL    Create_time: 2007-06-03 08:04:36     Update_time: 2007-06-03 08:04:36      Check_time: NULL Create_options:         Comment:1 row in set (0.00 sec)修改表名如果需要修改数据表的名称,可以在 ALTER TABLE 语句中使用 RENAME 子句来实现。尝试以下实例将数据表 testalter_tbl 重命名为 alter_tbl:mysql> ALTER TABLE testalter_tbl RENAME TO alter_tbl;alter其他用途修改存储引擎:修改为myisamalter table tableName engine=myisam;删除外键约束:keyName是外键别名alter table tableName drop foreign key keyName;修改字段的相对位置:这里name1为想要修改的字段,type1为该字段原来类型,first和after二选一,这应该显而易见,first放在第一位,after放在name2字段后面alter table tableName modify name1 type1 first|after name2;
  • [其他] 【总结】如何在有drop table业务情况下grant schema
    现象:当有drop table操作时grant schema可能会导致如下报错 ``` cache lookup failed for relation xxx ``` 规避办法: **1. 修改schema默认权限。修改后,该schema下新表的权限都会默认赋权给user1,但是不影响旧表** ``` alter default privileges in schema schemaname grant select on tables to user1; ``` **2. 生成修改旧表权限的sql文件** ``` select 'grant select on table ' || nspname || '.' || relname || ' to user1;' from pg_class c, pg_namespace n where c.relnamespace=n.oid and n.nspname='schemaname'; ``` **3. 执行生成的sql文件,即时报错也不影响赋权** 详细案例可以参考:https://bbs.huaweicloud.com/blogs/207326
  • [技术干货] MySQL为什么需要事务
    在银行业务中,有一条记账原则,即有借有贷,借贷相等。为了保证这种原则,每发生一笔银行业务,就必须确保会计账目上借方科目和贷方科目至少各记一笔,并且这两笔账要么同时成功,要么同时失败。如果出现只记录了借方科目,或者只记录了贷方科目的情况,就违反了记账原则。会出现记错账的情况。在银行的日常业务中,只要是同一银行(如都是中国农业银行,简称农行),一般都支持账户间的直接转账。因此,银行转账操作往往会涉及两个或两个以上的账户。在转出账户的存款减少一定金额的同时,转入账户的存款就要增加相应的金额。下面,在 MySQL 数据库中模拟一下上述提及的转账问题。假如要从张三的账户直接转账 500 元到李四的账户。首先需要创建账户表,存放用户张三和李四的账户信息。创建账户表和插入数据的 SQL 语句和运行结果如下所示:mysql> CREATE DATABASE mybank; Query OK, 1 row affected (0.02 sec) mysql> USE mybank; Database changed mysql> CREATE TABLE bank(     -> customerName VARCHAR(20),   #用户名     -> currentMoney DECIMAL(10,2)    #当前余额     -> )ENGINE=InnoDB DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.26 sec) mysql> INSERT INTO bank (customerName,currentMoney) VALUES('张三',1000);; Query OK, 1 row affected (0.07 sec) mysql> INSERT INTO bank (customerName,currentMoney) VALUES('李四',1); Query OK, 1 row affected (0.08 sec)查询 bank 数据表的 SQL 语句和运行结果如下:mysql> SELECT * FROM bank; +--------------+--------------+ | customerName | currentMoney | +--------------+--------------+ | 张三         |      1000.00 | | 李四         |         1.00 | +--------------+--------------+ 2 rows in set (0.02 sec)结果显示,张三和李四两个账户的余额总和为 1000+1=1001 元。下面开始模拟实现转账功能。从张三的账户直接转账 500 元到李四的账户,可以使用 UPDATE 语句分别修改张三的账户和李四的账户。张三的账户减少 500 元,李四的账户增加 500 元, SQL 语句如下所示:/*转账测试:张三转账给李四 500 元*/ #张三的账户少 500 元,李四的账户多 500 元 UPDATE bank SET currentMoney = currentMoney-500 WHERE customerName = '张三'; UPDATE bank SET currentMoney = currentMoney+500 WHERE customerName = '李四';正常情况下,执行以上的转账操作后,余额总和应保持不变,仍为 1001 元。但是,如果在这个过程的其中一个环节出现差错,如在张三的账户减少 500 元之后,这时发生了服务器故障,李四的账户没有立即增加 500 元,此时,第三方读取到两个账户的余额总和变为 500+1=501 元,即账户总额间少了 500 元。MySQL 为了解决此类问题,提供了事务。事务可以将一系列的数据操作**成一个整体进行统一管理,如果某一事务执行成功,则在该事务中进行的所有数据更改均会提交,成为数据库中的永久组成部分。如果事务执行时遇到错误,则就必须取消或回滚。取消或回滚后,数据将全部恢复到操作前的状态,所有数据的更改均被清除。MySQL 通过事务保证了数据的一致性。上述提到的转账过程就是一个事务,它需要两条 UPDATE 语句来完成。这两条语句是一个整体,如果其中任何一个环节出现问题,则整个转账业务也应取消,两个账户中的余额应恢复为原来的数据,从而确保转账前和转账后的余额总和不变,即都是 1001 元。
  • 【AppCube】数据调试台支持哪些SQL语句?
    目前数据调试台只支持查询数据,获取在查询过程中的执行计划,重建索引,查看索引,清理缓存,统计表记录数量,查看表中元数据,创建、删除、重建、搜索引擎索引,以及查看搜索引擎的索引信息等。具体支持的SQL语句说明如下:查询表数据AVG()函数:用于返回数值列的平均值。NULL值不包括在计算中。使用样例:SELECT AVG(column_name) FROM table_nameCOUNT()函数:用于返回表中的行数。使用样例:SELECT COUNT(column_name) FROM table_nameMAX()函数:用于返回一列中的最大值。NULL值不包括在计算中。使用样例:SELECT MAX(column_name) FROM table_nameMIN()函数:用于返回一列中的最小值。NULL值不包括在计算中。使用样例:SELECT MIN(column_name) FROM table_nameSUM()函数:用于返回数值列的总数(总额)。使用样例:SELECT SUM(column_name) FROM table_nameINNER JOIN(内连接或等值连接):获取两个表中字段匹配关系的记录。LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。RIGHT JOIN(右连接): 与LEFT JOIN相反,用于获取右表所有记录,即使左表没有对应匹配的记录。单列升序:select 列名 from 表名 order by 列名;单列降序:select 列名 from 表名 order by 列名 desc;多列升序:select 列名1, 列名2 from 表名 order by 列名1, 列名2;多列降序:select 列名1, 列名2 from 表名 order by 列名1 desc, 列名2 desc;多列混合排序:select 列名1, 列名2 from 表名 order by 列名1 desc, 列名2 asc;search语句当前对分组、通配符、去重distinct等功能暂未支持。search语句由于不支持通配符,in查询不能精准查询中文。search语句除了聚合函数(AVG、COUNT、MAX、MIN、SUM),其他必须带有where从句,否则报错。字符串类型默认都转为es中text类型,因此可以实现分词的倒排索引。由于默认未设置Fielddata=on(会很耗性能),所以字符串类型无法排序。不支持search语句where从句中有非可搜索字段,如不支持search * from myobject where t1 = 'abc' (此处t1为非可搜字段)。search语句目前只可进行单表搜索。search语句不支持HAVING子句、OFFSET。search语句不支持同时普通查询和聚合,例如:不支持“search count(列名),列名 from 列表名;”。search语句不支持列表名别名后“.*”全部查询,例如:不支持“search T.* from 列表名 as T where condition条件;”。text类型采用了英语分词器,因此大小写单复数不敏感,“movie”可匹配“Movies”。同sql语句一样,search语句也大小写不敏感。可搜字段的类型限制,当前加密文本、选项列表、选项列表(多项选择)和公式类型的字段不支持配置“是否可搜”,其他类型字段均可支持配置“是否可搜”。一般可通过select进行查询,语法为:SELECT <表名.字段名> FROM 表名 WHERE 条件表达式 GROUP BY 分组字段 ORDER BY 表名.排序字段名;通过search关键字进行查询,语法为:search <表名.字段名> FROM 表名 WHERE 条件表达式;search关键字进行查询,不同于select语法从数据库获取匹配数据,search语法是根据条件从elasticsearch中获得匹配数据。search查询会加速全文搜索,提升字段值匹配的效率,在数据量较大时,相比使用select语法查询会有很大的性能提升。用search关键字进行查询有个前提条件,被查询数据关联的对象字段需要支持search查询。即在AppCube开发环境中,在定义对象字段时,需要勾选字段属性“是否可搜”。勾选后,对象字段“IsSearchable”属性即被设置为“true”。配置后,在生成该对象数据记录时,该记录除了保存至数据库外,“IsSearchable”属性为“true”的字段值也将存储于elasticsearch中,便于后续用search关键字进行搜索。下面是search语句的一些限制和特点:Alias语法:给字段名或者表名指定别名,用于区分检索语句中的重复表名,也可用于重命名检索结果中的字段。语法样例:SELECT 列名 AS 列别名 FROM 表名;DISTINCT语法:有时查询结果会有某个字段值(列值)重复的数据记录,如果希望过滤重复的记录,您可使用该语法。语法样例:SELECT DISTINCT 列名称 FROM 表名称;通配符:在搜索数据库中的数据时,通配符“%”可替代任意数目字符(一个或者多个字符,甚至可替代零个字符),“_ ”可匹配任何单个字符。通配符需要和“LIKE”或者“NOT LIKE”搭配使用。例如找出以“b”开头的名字,名字的字段为name,语法样例:SELECT * FROM 表名称 WHERE name LIKE "b%";GROUP BY语法: 用于与合计函数结合,根据一个或多个列对结果集进行分组。例如,需要列出每个部门(字段为DEPT)最高薪水(字段为SALARY)的结果,语法样例:SELECT DEPT, MAX(SALARY) AS MAXIMUM FROM 表名STAFF GROUP BY DEPT;ORDER BY语法:用于根据指定的列对结果集进行排序。ORDER BY语句默认按照升序(ASC)对记录进行排序。如果您希望按照降序对记录进行排序,可以使用DESC关键字。语法样例如下:HAVING子句:用于为行分组或聚合组指定过滤条件。使用样例:SELECT column_name, aggregate_function(column_name) FROM table_name WHERE column_name operator value GROUP BY column_name HAVING aggregate_function(column_name) operator valueLIMIT操作符:LIMIT子句用于规定要返回的记录的数目,offset n表示的是从第n条数据开始取(程序的索引都是从0开始)。使用样例:SELECT column_name,column_name FROM table_name [WHERE Clause] [LIMIT N]IN操作符:用于WHERE子句中规定多个值。使用样例:SELECT column_name(s) FROM table_name WHERE column_name IN (value1,value2,...)JOIN关键字:联合多表查询。按照功能大致分为如下三类:使用样例:SELECT column_name(s) FROM table_name1 INNER JOIN table_name2 ON table_name1.column_name=table_name2.column_name函数目前不支持的语法有:BETWEEN操作符、UNION子句、SELECT INTO语句、FULL JOIN关键字、EXISTS子查询、嵌套select子查询、USING关键字、UCASE()函数、LCASE()函数、MID()函数、FIRST()函数、LAST()函数、Date函数、LEN()函数、ROUND()函数、FORMAT()函数。索引相关功能调试界面提供了查看表索引信息,重建索引的功能。但对具体字段加索引并没有该功能。重建索引是为了减小数据碎片化存储,提高数据查询效率。查看表索引信息,语法:show index重建索引,语法:rebuild index搜索引擎索引调试界面提供了显示、创建、删除、重建搜索引擎索引等功能,对具体字段加搜索引擎索引,需要在定义对象字段时,勾选字段属性“是否可搜”。创建搜索引擎索引,语法:searchindex create删除搜索引擎索引,语法:searchindex delete将数据从数据库刷新到搜索引擎索引,语法:searchindex rebuild显示重建搜索引擎索引信息,语法:searchindex show
  • [技术干货] 索引到底对查询速度有什么影响?
    索引是数据库优化中最常用也是最重要的手段之一,通过索引可以帮助用户解决大多数的 SQL 性能问题。多数情况下,查询速度很慢时,加上索引便能解决问题。但也并非总是如此,因为优化不是件简单的事情。但是如果你不使用索引,在许多情况下,尝试通过其它途径来提高性能都纯粹是在浪费时间。应该首先使用索引来最大程度的改善性能,然后再看看是否还有其它有用的技术。索引提供了高效访问数据的方法,能够快速的定位表中的某条记录,加快数据库查询的速度,从而提高数据库的性能。如果查询时不使用索引,那么查询语句将查询表中的所有字段。这样查询的速度会很慢。使用索引进行查询,查询语句不必读完表中的所有记录,而只查询索引字段。这样可以减少查询的记录数,达到提高查询速度的目的。下面通过对比使用索引和不使用索引来分析索引对查询速度的影响。例 为了便于大家更好的理解,分析之前,我们先查询一下 tb_students_info 数据表中的记录,SQL 语句和运行结果如下:mysql> SELECT * FROM tb_students_info; +----+------+ | id | name | +----+------+ |  1 | 张三 | |  2 | 李四 | |  3 | 王五 | |  4 | 赵六 | |  5 | 周七 | |  6 | 吴八 | |  7 | 朱九 | |  8 | 苏十 | +----+------+ 8 rows in set (0.02 sec)使用 EXPLAIN 分析未使用索引时的查询情况,SQL 语句和运行结果如下:mysql> EXPLAIN SELECT * FROM tb_students_info WHERE name='张三' \G *************************** 1. row ***************************            id: 1   select_type: SIMPLE         table: tb_students_info    partitions: NULL          type: ALL possible_keys: NULL           key: NULL       key_len: NULL           ref: NULL          rows: 8      filtered: 12.50         Extra: Using where 1 row in set, 1 warning (0.00 sec)由结果可以看到,rows 列的值是 8,说明查询语句扫描了表中的 8 条记录。没有索引的表就相当于一组无序的行,如果我们想找到某条记录就必须检查表的每一行,看看它是否与那个期望值相匹配。这是一个全表扫描操作,其效率很低,如果表很大,而且仅有少数几条记录与搜索条件相匹配,那么整个扫描过程的效率将会超级低。在 tb_students_info 表的 name 字段添加索引,SQL 语句和运行结果如下:mysql> CREATE INDEX index_name ON tb_students_info(name); Query OK, 8 rows affected (0.14 sec)使用 EXPLAIN 再次执行上面的查询语句,SQL 语句和运行结果如下:mysql> EXPLAIN SELECT * FROM tb_students_info WHERE name='张三' \G *************************** 1. row ***************************            id: 1   select_type: SIMPLE         table: tb_students_info    partitions: NULL          type: ref possible_keys: index_name           key: index_name       key_len: 63           ref: const          rows: 1      filtered: 100.00         Extra: NULL 1 row in set, 1 warning (0.00 sec)结果显示,rows 列的值为 1,表示这个查询语句只扫描了表中的 1 条记录。创建索引后访问的行由 8 行减少到 1 行,其查询速度自然比扫描 8 条记录快。而且 possible_keys 和 key 的值都是 index_name,这说明查询时使用了 index_name 索引。所以,在查询操作中,使用索引不仅能自动优化查询效率,还会降低服务器的开销。注意:由于 tb_students_info 表中记录较少,所以在这没有分析运行时间。表中记录多时,运行时间的差异也会体现出索引对查询速度的影响。
总条数:865 到第 页
上滑加载中