• DML(Data Manipulation Language)数据操纵语言:

适用范围:对数据库中的数据进行一些简单操作,如insert,delete,update,select等.

  • DDL(Data Definition Language)数据定义语言:

适用范围:对数据库中的某些对象(例如,database,table)进行管理,如CREATE,ALTER和DROP.

  • 区别:

    • DML操作是可以手动控制事务的开启、提交和回滚的。

    • DDL操作是隐性提交的,不能rollback

  • 名词解释(仅限本文)

    • <databaseName> 数据库名称
    • <tableName> 数据表名称
    • <fieldName> 字段名称
    • <aliasName> 别名
    • <condition> 条件
    • <number> 数值
    • <offset> 偏移量
    • <value>
    • <func> 函数
    • <OP> 操作符
USE <databaseName>; #使用数据库
show databases; # 返回可用数据库的列表
show tables; # 返回使用数据库中可用的表
show columns from <tableName>; # 返回表中的字段信息
show status; # 用于显示广泛的服务器状态信息
show create database <databaseName>; # 显示创建数据库的MySQL语句
show create table <tableName>; # 显示创建表的MySQL语句
show grants; # 显示授予用户的安全权限
show errors; # 显示服务器的错误
show warnings; # 显示服务器警告信息

数据类型

目的

  • 数据类型允许限制可存储在列中的数据。例如,数值数据类型列只能接受数值。

  • 数据类型允许在内部更有效地存储数据。可以用一种比文本串更简洁的格式存储数值和日期时间值。

  • 数据类型允许变换排序顺序。如果所有数据都作为串处理,则1位于10之前,而10又位于2之前(串以字典顺序排序,从左边开始比较,一次一个字符)。作为数值数据类型,数值才能正确排序。

串数据

定长串接受长度固定的字符串,其长度是在创建表时指定的。例如,名字列可允许30个字符,而社会安全号列允许11个字符(允许的字符数目中包括两个破折号)。定长列不允许多于指定的字符数目。它们分配的存储空间与指定的一样多。因此,如果串Ben存储到30个字符的名字字段,则存储的是30个字符,CHAR属于定长串类型。变长串存储可变长度的文本。有些变长数据类型具有最大的定长,而有些则是完全变长的。不管是哪种,只有指定的数据得到保存(额外的数据不保存)TEXT属于变长串类型。

既然变长数据类型这样灵活,为什么还要使用定长数据类型?回答是因为性能。MySQL处理定长列远比处理变长列快得多。此外,MySQL不允许对变长列(或一个列的可变部分)进行索引。这也会极大地影响性能。

数据类型说明
CHAR1~255个字符的定长串它的长度必须在创建时指定,否则MySQL假定为CHAR(1)
ENUM接受最多64K个串组成的一个预定义集合的某个串
LONGTEXT与TEXT相同,但最大长度为4GB
MEDIUMTEXT与TEXT相同,但最大长度为16K
SET接受最多64个串组成的一个预定义集合的零个或多个串
TEXT最大长度为64K的变长文本
TINYTEXT与TEXT相同,但最大长度为255字节
VARCHAR长度可变,最多不超过255字节。如果在创建时指定为VARCHAR(n),则可储存0到n个字符长度n<=255

日期时间数据

数据结构说明
DATE表示1000-01-01~9999-12-31的日期格式为YYYY-MM-DD
DATETIMEDATE和TIME的组合
TIMESTAMP功能和DATETIME相同(但范围较小)
TIME格式为HH:MM:SS
YEAR用2位数字表示范围是70(1970年)~69(2069年),用4位数字表示是1901~2155年

数值数据

数据类型说明
BIT位字段 1~64位
BIGINT整数值 -9223372036854775808~9223372036854775807,UNSIGNED 0~18446744073709551615
BOOLEAN布尔标志 0/1
DECIMAL精度可变的浮点值
DOUBLE双精度浮点值
FLOAT单精度浮点值
INT整数值 -2147483648~2147483647,UNSIGNED 0~4294967295
MEDIUMINT整数值支持-8388608~8388607,UNSIGNED 0~16777215
REAL4字节浮点值
SMALLINT整数值 支持-32768~32767,UNSIGNED 0~65535
TINYINT整数值 支持-128~127, UNSIGNED 0~255

二进制数据

数据类型说明
BLOBBlob最大长度为64KB
MEDIUMBLOBBlob最大长度为16MB
LONGBLOBBlob最大长度为4GB
TINYBLOBBlob最大长度为255字节

检索数据

select <fieldName>,<fieldName>,···,···, from <tableName>; # 从指定的表中检索一个或多个名为<fieldName>的列
select * from <tableName>; # 从指定的表中检索所有字段列"*"是一个通配符
select distinct <fieldName> from <tableName>; # 显示唯一的字段distinct应用于所有列而不仅是前置它的列
select ç from <tablelName> limit <number>;
# 使用select语句检索单个列或多个列返回不多于指定number行数
select <fieldName> from <tableName> limit <offset>,<number>;
# 使用select语句检索单个列或多个列返回从offset的开始的不多于指定number的行数offset是从0开始计算的

排序检索数据

select <fieldName> from <tableName> order by <fieldName>,<fieldName>,···,···;
# 用select语句检索出的数据可使用order by子语句,order by子句取一个或多个列进行排序
select <fieldName> from <tableName> order by <fieldName>,<fieldName>,···,···DESC(ASC);
# 用select语句检索出的数据可使用order by子语句,order by子句取一个或多个列进行排序默认为升序排列,DESC指定为降序排列

过滤数据

select <fieldName> from <tableName> where <condition>;
# 根据where后的条件过滤检索数据 同时使用order by和where子语句时应该让order by位于where之后
select <fieldName> from <tableName> where <fieldName>
BETWEEN 5 AND 10;
# 过滤出5到10之间的数据行包括指定的开始值和结束值也就是说包括5和10的记录
select <fieldName> from <tableName> where <fieldName> IS NULL;
# 从检索到的数据中过滤空值
  • NULL与不匹配

    在通过过滤选择出不具有特定值的行时,你可能希望返回具有NULL值的行。但是,不行。因为未知具有特殊的含义,数据库不知道它们是否匹配,所以在匹配过滤或不匹配过滤时不返回它们。因此,在过滤数据时,一定要验证返回数据中确实给出了被过滤列具有NULL的行。

  • where子语句操作符

操作符说明
=等于
<>不等于
!=不等于
<小于
<=小于等于
>大于
>=大于等于
BETWEEN在指定两个值之间

数据过滤

select <fieldName>,···,··· from <tableName> where <fieldName> <OP> <Value> and <fieldName> <OP> <Value>;
# 通过不止一个列进行过滤多个过滤条件用and连接
select <fieldName>,···,··· from <tableName> where <fieldName> <OP> <Value> or <fieldName> <OP> <Value>;
# 满足任一条件进行过滤
select <fieldName>,···,··· from <tableName> where (<fieldName> <OP> <Value> or <fieldName> <OP> <Value>) and <fieldName> <OP> <Value>;
# or和and是有计算次序的SQL中and的计算次序优先级比or高所以要用"()"来提升计算次序
select <fieldName>,···,··· from <tableName> where <fieldName> in (<value>,<Value>,···,···);
# IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配IN操作符完成与OR相同的功能
select <fieldName>,···,··· from <tableName> where <fieldName> not in (<value>,<Value>,···,···);
# NOT操作符有且只有一个功能,那就是否定它之后所跟的任何条件。
  • 为什么要使用IN操作符?
    • 在使用长的合法选项清单时,IN操作符的语法更清楚且更直观。
    • 在使用IN时,计算的次序更容易管理(因为使用的操作符更少)。
    • IN操作符一般比OR操作符清单执行更快。
    • IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建立WHERE子句。
    • MySQL支持使用NOT 对IN 、BETWEEN 和EXISTS子句取反。

通配符过滤

select <fieldName>,···,···,from <tableName> like '<OP>';
  • 通配符
通配符说明
%替代 0 个或多个字符
_替代一个字符
  • 不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。

  • 在确实需要使用通配符时,除非绝对有必要,否则不要把它们用

  • 在搜索模式的开始处。把通配符置于搜索模式的开始处,搜索起来是最慢的。

  • 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据

使用正则表达式过滤数据

select <fieldName>,···,···, from <tbaleName> where <fieldName> REGEXP <OP>;
  • 正则表达式
符号说明
^匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
.匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
[...]字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^...]负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
p1|p2|p3匹配 p1 或 p2 或 p3
*匹配前面的子表达式零次或多次。
+匹配前面的子表达式一次或多次。
{n}n 是一个非负整数。匹配确定的 n 次。
{n,m}m 和 n 均为非负整数,其中n <= m。

创建计算字段

select Concat(<fieldName>,<filedName>) from <tableName>;
  • Concat()拼接串,即把多个串连接起来形成一个较长的串。

  • Concat()需要一个或多个指定的串,各个串之间用逗号分隔。

select Concat(<fieldName>,<filedName>) AS <aliasName> from <tableName>;
# 别名(alias)是一个字段或值的替换名。别名用AS关键字赋予。
select <fieldName1>,<fieldName2>,<fieldName1> <OP> <fieldName> AS <aliasName> from <tableName>;
# 可以对字段进行算术运算结果生成新的字段
  • OP
操作符说明
+
-
*
/

数据处理函数

文本处理函数

select <fieldName>,<func>(<fieldName>) as <alias> from <tableName>;
  • 常用的文本处理函数
函数说明
Left()返回串左边的字符
Length()返回字符串的长度
Locate()找出串的一个子串
Lower()将串转换为小写
LTrim()去掉串左边的空格
Right()返回串右边的字符
RTrim()去掉串右边的空格
Soundex()返回SOUNDEX值
SubString()返回子串的字符
Upper()将串转换为大写

日期时间处理函数

  • 常用的日期时间处理函数
函数说明
AddDate()增加一个日期(天、周等)
AddTime()增加一个时间(时、分等)
CurDate()返回当前日期
CurTime()返回当前时间
Date()返回日期时间的日期部分
DateDiff()计算两个日期之差
Date_Add()高度灵活的日期运算函数
Date_Format()返回一个格式化的日期或时间串
Day()返回一个日期的天数部分
DayOfWeek()对于一个日期,返回对应的星期几
Hour()返回一个时间的小时部分
Minute()返回一个时间的分钟部分
Month()返回一个日期的月份部分
Now()返回当前日期和时间
Second()返回一个时间的秒部分
Time()返回一日期时间的时间部分
Yesr()返回一个日期的年份部分
  • 日期必须为格式yyyy-mm-dd。因此,2005年9月1日,给出为2005-09-01
select <fieldName>,···,··· from <tableName> where Date(<filedName>) = 'yyyy-mm-dd';

数值处理函数

  • 常用的数值处理函数
函数说明
Abs()返回一个树的绝对值
Cos()返回一个角度的余弦
Exp()返回一个数的指数值
Mod()返回除操作的余数
Pi()返回圆周率
Rand()返回一个随机数
Sin()返回一个角度的正弦
Sqrt()返回一个数的平方根
Tan()返回一个角度的正切

汇总数据

  • 聚集函数
函数说明
AVG()返回某列的平均值
COUNT()返回某列的行数
MAX()返回某列的最大值
MIN()返回某列的最小值
SUM()返回某列值之和
  • 基本使用
select <func>(<fieldName>) as <aliasName> from <tableName>;
  • 聚集不同值
select <func>(distinct <fieldName>) as <aliasName> from <tableName> where <fieldName> <OP> <Value>;

如果指定列名,则DISTINCT只能用于COUNT()DISTINCT不能用于COUNT(*),因此不允许使用COUNT(DISTINCT),否则会产生错误。类似地,DISTINCT必须使用列名,不能用于计算或表达式。

  • 组合聚集
select count(*) as <aliasName>,
			 MIN(<fieldName>) as min,
			 Max(<fieldName>) as max,
			 AVG(<fieldName>) as avg
from <tableName>;
# SELECT语句可根据需要包含多个聚集函数

数据分组

select <fieldName>,···,··· from <tableName> group by <fieldName>;
  • group by 子句规则

    • GROUP BY子句可以包含任意数目的列。这使得能对分组进行嵌套,为数据分组提供更细致的控制。
    • 如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总。换句话说,在建立分组时,指定的所有列都一起计算(所以不能从个别的列取回数据)。
    • GROUP BY子句中列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。
    • 除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出。
    • 如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组。
    • GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。
  • 使用WITH ROLLUP关键字,可以得到每个分组以及每个分组汇总级别(针对每个分组)的值。

select <fieldName>,···,··· from <tableName> group by <fieldName> with rollup;

过滤分组

  • HAVING支持所有WHERE操作符

WHERE子句的条件(包括通配符条件和带多个操作符的子句)。所学过的有关WHERE的所有这些技术和选项都适用于HAVING。它们的句法是相同的,唯一的差别是WHERE过滤行,而HAVING过滤分组。

select <fieldName>,···,··· from <tableName> group by <fieldName> having <condition>;

分组排序

不要忘记ORDER BY 一般在使用GROUP BY子句时,应该也给出ORDER BY子句。这是保证数据正确排序的唯一方法。千万不要仅依赖GROUP BY排序数据。

select <fieldName>,···,··· from <tableName> group by <fieldName> having <condition> order by <condition>;

SELECT语句顺序

子句说明是否必须使用
select要返回的列或表达式
from从中检索数据的表仅在从表选择数据时使用
where行级过滤
group by分组说明仅在按组计算聚集时使用
having组级过滤
order by输出排序顺序
limit要检索的行数

子查询

  • 先分析问题将问题拆解成单条SELECT语句根据需求进行合并

使用子查询过滤数据

select <fieldName> 
from <tableName> 
where <fieldName> in (select <fieldName>
                      from <tableName>
                      where <condition>);
select <fieldName>,···,··· 
from <tableName>
where <fieldName> in(select <fieldName>
                     from <tableName>
                     where <fieldName> in(select <fieldName>
                                         	from <tableName>
                                         	where <condition>));

作为计算字段使用子查询

select <fieldName>,
			 <fieldName>,
			 (select count(*)
       	from <tableName>
        where <condition>) as <aliasName>
from <tableName>
order by <fieldName>;

连接表

内连接

  • 内连接又称等值连接
  • 使用inner join关键字
select <fieldName>,···
from <tableName> inner join <tableName>
on <tableName>.<fieldName> = <tableName>.<fieldName>;
  • 使用where做等值连接
select <fieldName>,···
from <tableName>,<tableName>,···
where <tableName>.<fieldName> = <tableName>.<fieldName>;

自联结

  • 其实就是同一张表自己连接自己
select <aliasName>.<fieldName>,<aliasName>.<fieldName>
from <tableName> as p1,<tableName> as p2
where p1.<fieldName> = p2.<fieldName>
and p2.<fieldName> = <Value>
select p1.prod_id,p1.
from products as p1,products as p2
where p1.vend_id = p2.vend_id
and p2.prod_id = 'DTNTR'

自然连接

  • 自然连接是把同名列通过等值测试连接起来的,同名列可以有多个。

  • 内连接和自然连接的区别:内连接提供连接的列,而自然连接自动连接所有同名列。

select c.*,o.order_num,o.order_date,ol.prod_id,ol.quantity,ol.item_price
from customers as c,orders as o , orderitems as ol
where c.cust_id = o.cust_id
and ol.order_num = o.order_num
and prod_id = 'FB'

外部连接

  • 外连接保留了没有关联的那些行。分为左外连接,右外连接以及全外连接,左外连接就是保留左表没有关联的行。

  • 左外连接(left join / left outer join): 满足on条件表达式,左外连接是以左表为准,返回左表所有的数据,与右表匹配的则有值,没有匹配的则以空(null)取代。

  • 右外连接(right join / right outer join):满足on条件表达式,右外连接是以右表为准,返回右表所有的数据,与左表匹配的则有值,没有匹配的则以空(null)取代。

  • 全外连接(full join / full outer join):满足on条件表达式,返回两个表符合条件的所有行,a表没有匹配的则a表的列返回nullb表没有匹配的则b表的列返回null,即返回的是左连接和右连接的并集。

  • 交叉连接(cross join):交叉连接将会返回被连接的两个表的笛卡尔积,返回结果的行数等于两个表行数的乘积。

组合查询

  • 使用 UNION 来组合两个查询,如果第一个查询返回 M 行,第二个查询返回 N 行,那么组合查询的结果一般为 M+N 行。

  • 每个查询必须包含相同的列、表达式和聚集函数。

  • 默认会去除相同行,如果需要保留相同行,使用 UNION ALL。

  • 只能包含一个 ORDER BY 子句,并且必须位于语句的最后。

SELECT col
FROM mytable
WHERE col = 1
UNION
SELECT col
FROM mytable
WHERE col =2;

视图

  • 视图是虚拟的表,本身不包含数据,也就不能对其进行索引操作。

  • 对视图的操作和对普通表的操作一样。

  • 数据库中只存放了视图的定义,而没有存放视图中的数据,这些数据存放在原来的表中。

  • 使用视图查询数据时,数据库系统会从原来的表中取出对应的数据。

  • 视图中的数据依赖于原来表中的数据,一旦表中数据发生改变,显示在视图中的数据也会发生改变。

视图具有如下好处:

  • 简化复杂的 SQL 操作,比如复杂的连接;
  • 只使用实际表的一部分数据;
  • 通过只给用户访问视图的权限,保证数据的安全性;
  • 更改数据格式和表示。
CREATE VIEW myview AS
SELECT Concat(col1, col2) AS concat_col, col3*col4 AS compute_col
FROM mytable
WHERE col5 = val;

视图与表的区别

  • 表要占用磁盘空间,视图不需要
  • 视图不能添加索引
  • 使用视图可以简化查询
  • 视图可以提高安全性

储存过程

存储过程可以看成是对一系列 SQL 操作的批处理。

使用存储过程的好处:

  • 代码封装,保证了一定的安全性;
  • 代码复用;
  • 由于是预先编译,因此具有很高的性能。

命令行中创建存储过程需要自定义分隔符,因为命令行是以 ; 为结束符,而存储过程中也包含了分号,因此会错误把这部分分号当成是结束符,造成语法错误。

包含 in、out 和 inout 三种参数。

给变量赋值都需要用 select into 语句。

每次只能给一个变量赋值,不支持集合的操作。

delimiter //

create procedure myprocedure( out ret int )
    begin
        declare y int;
        select sum(col1)
        from mytable
        into y;
        select y*y into ret;
    end //

delimiter ;
call myprocedure(@ret);
select @ret;

优点

  • 由于不要求反复建立一系列处理步骤,这保证了数据的完整性。如果所有开发人员和应用程序都使用同一(试验和测试)存储过程,则所使用的代码都是相同的。这一点的延伸就是防止错误。需要执行的步骤越多,出错的可能性就越大。防止错误保证了数据的一致性。

  • 简化对变动的管理。如果表名、列名或业务逻辑(或别的内容)有变化,只需要更改存储过程的代码。使用它的人员甚至不需要知道这些变化。这一点的延伸就是安全性。通过存储过程限制对基础数据的访问减少了数据讹误(无意识的或别的原因所导致的数据讹误)的机会。

  • 提高性能。因为使用存储过程比使用单独的SQL语句要快。

  • 存在一些只能用在单个请求中的MySQL元素和特性,存储过程可以使用它们来编写功能更强更灵活的代码

游标

在存储过程中使用游标可以对一个结果集进行移动遍历。游标主要用于交互式应用,其中用户需要对数据集中的任意行进行浏览和修改。

使用游标的四个步骤:

  • 声明游标,这个过程没有实际检索出数据;

  • 打开游标;

  • 取出数据;

  • 关闭游标;

delimiter //
create procedure myprocedure(out ret int)
    begin
        declare done boolean default 0;

        declare mycursor cursor for
        select col1 from mytable;
        # 定义了一个 continue handler,当 sqlstate '02000' 这个条件出现时,会执行 set done = 1
        declare continue handler for sqlstate '02000' set done = 1;

        open mycursor;

        repeat
            fetch mycursor into ret;
            select ret;
        until done end repeat;

        close mycursor;
    end //
 delimiter ;

触发器

基本术语:

  • 事务(transaction)指一组 SQL 语句;
  • 回退(rollback)指撤销指定 SQL 语句的过程;
  • 提交(commit)指将未存储的 SQL 语句结果写入数据库表;
  • 保留点(savepoint)指事务处理中设置的临时占位符(placeholder),你可以对它发布回退(与回退整个事务处理不同)。

不能回退 SELECT 语句,回退 SELECT 语句也没意义;也不能回退 CREATEDROP 语句。

MySQL 的事务提交默认是隐式提交,每执行一条语句就把这条语句当成一个事务然后进行提交。当出现 START TRANSACTION语句时,会关闭隐式提交;当 COMMITROLLBACK 语句执行后,事务会自动关闭,重新恢复隐式提交。

设置 autocommit0可以取消自动提交;autocommit 标记是针对每个连接而不是针对服务器的。

如果没有设置保留点,ROLLBACK 会回退到 START TRANSACTION 语句处;如果设置了保留点,并且在 ROLLBACK中指定该保留点,则会回退到该保留点。

START TRANSACTION
// ...
SAVEPOINT delete1
// ...
ROLLBACK TO delete1
// ...
COMMIT

创建表

CREATE TABLE mytable (
  # int 类型,不为空,自增
  id INT NOT NULL AUTO_INCREMENT,
  # int 类型,不可为空,默认值为 1,不为空
  col1 INT NOT NULL DEFAULT 1,
  # 变长字符串类型,最长为 45 个字符,可以为空
  col2 VARCHAR(45) NULL,
  # 日期类型,可为空
  col3 DATE NULL,
  # 设置主键为 id
  PRIMARY KEY (`id`));

修改表

  • 添加列
ALTER TABLE mytable
ADD col CHAR(20);
  • 删除列
ALTER TABLE mytable
DROP COLUMN col;
  • 删除表
DROP TABLE mytable;

插入

  • 普通插入
INSERT INTO mytable(col1, col2)
VALUES(val1, val2);
  • 插入检索出来的数据
INSERT INTO mytable1(col1, col2)
SELECT col1, col2
FROM mytable2;
  • 将一个表的内容插入到一个新表
CREATE TABLE newtable AS
SELECT * FROM mytable;

更新

UPDATE mytable
SET col = val
WHERE id = 1;

删除

DELETE FROM mytable
WHERE id = 1;
  • 清空表数据保留表结构
TRUNCATE TABLE mytable;

使用更新和删除操作时一定要用 WHERE 子句,不然会把整张表的数据都破坏。可以先用 SELECT 语句进行测试,防止错误删除。

权限管理

MySQL 的账户信息保存在 mysql 这个数据库中。

USE mysql;
SELECT user FROM user;

创建账户

新创建的账户没有任何权限。

CREATE USER myuser IDENTIFIED BY 'mypassword';

修改账户名

RENAME USER myuser TO newuser;

删除账户

DROP USER myuser;

查看权限

SHOW GRANTS FOR myuser;

授予权限

账户用 username@host 的形式定义,username@% 使用的是默认主机名。

GRANT SELECT, INSERT ON mydatabase.* TO myuser;

删除权限

GRANT 和 REVOKE 可在几个层次上控制访问权限:

  • 整个服务器,使用 GRANT ALL 和 REVOKE ALL;
  • 整个数据库,使用 ON database.*;
  • 特定的表,使用 ON database.table;
  • 特定的列;
  • 特定的存储过程。
REVOKE SELECT, INSERT ON mydatabase.* FROM myuser;Copy to clipboardErrorCopied

更改密码

必须使用 Password() 函数进行加密。

SET PASSWROD FOR myuser = Password('new_password');