-
1. 声明游标游标主要由结果集合游标位置组成的,结果集是 SELECT 语句执行后返回的,而游标位置是指向返回结果集中的指针;使用游标前必须对游标进行声明;在 SQL Server 数据库中,使用 DECLARE CURSOR 语句对游标进行声明;游标的声明要对游标的滚动行为、游标所操作的结果集进行设置;游标的声明语法格式如下:1234567DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ] [ FORWARD_ONLY | SCROLL ] [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ] [ TYPE_WARNING ] FRO select_seatement [ FRO UPDATE [ OF column_name [,..n] ] ]cursor_name:指定要声明游标的名称;LOCAL:指定游标的作用域,LOCAL 表示游标的作用域局部;FORWARD_ONLY:指定游标只能从第一个记录向下滚动到最后一条记录;STATIC:定义一个游标使用数据的临时副本,对游标的所有请求都通过 tempdb 中的临时表得到应答,提取数据时对该游标不能反映基表数据修改的结果;静态游标不允许更改;DYNAMIC:表示当游标滚动时,动态游标反映对结果集内所有数据的更改;KEYSET:指定打开游标时,游标中记录顺序和成员身份已被固定,对进行唯一标识的键集内置在 tempdb 内一个称为 keyset的表中;READ_ONLY|SCROLL_LOCKS|OPTIMISTIC:第一个参数表示游标为只读游标,SCROLL_LOCKS 表示在使游标的结果集时放置锁,当游标对数据进行读取时,数据库会对记录进行锁定,保证数据的一致性;OPTIMISTIC的作用在于通过游标读取数据,若读取数据之后被更改,那么通过游标定位进行的更新和删除操作不成功;select_statement:指定游标所用结果集的 SELECT 语句;注意: 若 GROBAL 和 LOCAL 参数都未指定,默认值就由 default to local cursor 数据选项的设置控制;例子1:声明名称为 cursor_B 的标准游标,如下所示:1declare cursor_B cursorfor select * from B上述定义了一个名为 cursor_B 的游标,游标所操作的结果集从 SELECT 语句中得到;例子2:声明名称为 cursor_B_read de 的只读游标,如下所示:123declare cursor_B_read cursorfor select * from Bfor read only上述代码中与标准的定义游标过程相比多出了 FOR READ ONLY 语句,表名该游标的记录只能被读取,不能进行被读取,不能进行更改;例子3:声明名称称为 curesor_B_update 的更改标签,如下所示:123declare cursor_B_update cursorfor select * from Bfor update2. 打开游标使用 OPEN 语句打开 Transa-SQL 服务器游标,执行 OPEN 语句的过程,按照 SELECT 语句填充数据,当打开游标时,游标的位置在数据集的第一行,打开游标的语法格式如下:1OPEN [GLOBAL] cursor_name | cursor_variable _name例子1:打开游标 cursor_B,如下所示:1open cursor_B打开游标后,可进行数据操作;打开全局游标:1open global cursor_B打开游标是对数据库进行一些 SQL SELECT 的操作,将耗费一段时间,取决于使用的系统性能和这条语句的复杂性;3. 读取游标中的数据打开游标后就能读取数据集中的记录,用 FETCH 语句能对数据集总的数据进行某一行读取;FETCH 语法的格式如下:123456789FETCH[ [ NEXT | PRIOR | FIRST | LAST| ABSOLUTE {n | @nvar}| relative {n | @nvar}]FROM]{{ [ GLOBAL ] cursor_name } | @cursor_variable_name }{ INTO @variable_name [,...n] }NEXT:返回结果集中当前行的下一行记录,若读取的是第一行记录,就返回第一行;NEXT 为默认的读取选项;PRIOR:返回结果集中当前行的一条记录,若当前行的第一条记录,就不返回,将游标定义到第一条记录;FIRST:返回结果集中的第一条记录,并把第一行作为当前行;LAST:返回结果集中的最后一条记录,并把最后一行作为当前行;ABSOLUTE n:若 n 为正数,就返回从游标末尾开始的 n 行,并返回作为新的当前行;若 n 为负值,就返回从游标 末尾开始的第 n 行,并返回行为作为新的当前行;若 n 为 0,就返回当前行;RELATIVE n:若 n 为正数,就返回从当前行开始的第 n 行;若 n 为负数,就返回当前行之前的第 n 行;若为 0,就返回当前行;GLOBAL:指定游标的作用域为全局游标;cursor_name:指定要打开游标的名称;INTO@variable_name[, ... n]:将记录中提取的字段信息存储到局部变量中;例子 1:利用之前创建的游标 cursor_B_read 检索 B表中的记录12345678declare cursor_B_read cursorfor select * from Bopen cursor_B_readfetch next from cursor_B_readwhile @@FETCH_STATUS = 0beginfetch next from cursor_B_readend在使用游标对数据进行读取时可声明一个游标变量,使用关键字 SET 对游标进行赋值;对游标赋值的操作步骤:先创建一个游标,打开后将值赋予变量,最后通过 FETCH 语句从变量中读取值;例子 2:创建 cursor_S 游标,并将值赋予 @Mchr 游标变量1234567891011121314declare @Mchr cursordeclare cursor_S cursor forselect * from s;open cursor_Sset @Mchr = cursor_Sfetch next from @Mchrwhile @@FETCH_STATUS = 0beginfetch next from @Mchrendclose @Mchrdeallocate @Mchr先声明了游标变量 @Mchr,再创建一个 cursor_S 游标打开游标后将值赋给 @Mchr,最后用 FEECH 读取变量中的数据内容;FETCH 语法是游标使用的核心,使用游标能逐条记录到查询结果;已经声明并打开一个游标后,就能将数据放入任意的变量中;在 FETCH 语句中,读者能指定游标的名称和目标的变量名称;注意: 若在 SELECT 语句中使用了 DISTINCT、UNION、GROUP BY 语句,且在选择中包含了聚合表达式,游标就自动为 INSENSITIVE 的游标;4. 关闭游标SQL Server 数据库在创建一个游标后,数据库服务器会开辟一片存储空间用于存放游标返回的数据集;在游标使用完后一定要养成关闭游标的习惯,这样就能释放服务器为游标开辟的内存空间;在处理完游标中的数据之后,用 CLOSE 命令能关闭一个已打开的游标;语法格式如下:1CLOSE [ CLOBAL ] cursor_name | cursor_variable_naem例子1:关闭名称为 cursor_B 的游标1close cursor_B游标可应用在存储过程、触发器等中,若在声明游标上与释放游标之间使用了事务结构,在结束事务时游标就会自动关闭;具体步骤如下:声明一个游标;打开游标;读取游标;BEGIN TRANSATION;数据处理;COMMIT TRANSATION;注意: 打开游标后,SQL Server 服务器会专门为游标开辟一定的内存空间用于存放游标操作的数据结果集,同时游标的使用也会根据具体情况对某些数据进行封锁;所以在不使用游标时一定要关闭游标,以通知服务器释放游标所占用的资源;关闭游标后,可再次打开游标,在一个批处理中,也能多次打开和关闭游标;5. 释放游标当用户确定某个游标不再使用时,应当即使使用 DEALLOCATE 命令释放游标,SQL Server 将删除这个游标的数据结构;语法如下所示:1DEALLOCATE [GLOBAL]游标被释放后据不能再使用 OPEN 命令再次打开了;关闭游标和释放游标的区别在于,关闭没有把游标运行所占用的内存空间释放,若再次打开游标,还能照常使用,若是释放,就是将游标占用的资源释放;若再想使用游标,就必须重新建立;
-
一:认识游标游标是SQL Server的一种数据访问机制,它允许用户访问单独的数据行。用户可以对每一行进行单独的处理,从而降低系统开销和潜在的阻隔情况,用户也可以使用这些数据生成的SQL代码并立即执行或输出。1.游标的概念游标是一种处理数据的方法,主要用于存储过程,触发器和 T_SQL脚本中,它们使结果集的内容可用于其它T_SQL语句。在查看或处理结果集中向前或向后浏览数据的功能。类似与C语言中的指针,它可以指向结果集中的任意位置,当要对结果集进行逐条单独处理时,必须声明一个指向该结果集中的游标变量。SQL Server 中的数据操作结果都是面向集合的,并没有一种描述表中单一记录的表达形式,除非使用WHERE子句限定查询结果,使用游标可以提供这种功能,并且游标的使用和操作过程更加灵活、高效。2.游标的优点SELECT 语句返回的是一个结果集,但有时候应用程序并不总是能对整个结果集进行有效地处理,游标便提供了这样一种机制,它能从包括多条记录的结果集中每次提取一条记录,游标总是与一跳SQL选择语句相关联,由结果集和指向特定记录的游标位置组成。使用游标具有一下优点:(1).允许程序对由SELECT查询语句返回的行集中的每一次执行相同或不同的操作,而不是对整个集合执行同一个操作。(2).提供对基于游标位置中的行进行删除和更新的能力。(3).游标作为数据库管理系统和应用程序设计之间的桥梁,将两种处理方式连接起来。3.游标的分类SQL Server支持3中游标实现:(1).Transact_SQL游标基于DECLARE CURSOR 语法,主要用于T_SQL脚本,存储过程和触发器。T_SQL游标在服务器上实现,并由从客户端发送到服务器的T_SQL语句管理,它们还可能包含在批处理,存储过程或触发器中。(2).应用程序编程接口(API)服务器游标支持OLE DB和ODBC中的API游标函数,API服务器游标在服务器上实现。每次客户端应用程序调用API游标函数时,SQL Server Native Client OLE DB访问接口或ODBC驱动程序会把请求传输到服务器,以便对API服务器游标进行操作。(3).客户端游标由SQL Server Native Client ODBC驱动程序和实现ADO API的DLL在内部实现。客户端游标通过在客户端高速缓存所有结果集中的行来实现。每次客户端应用程序调用API游标函数时,SQL Server Native Client ODBC驱动程序或ADO DLL会对客户端上告诉缓存的结果集中的行执行游标操作。由于T_SQL游标和服务器游标都在服务器上实现,所以它们统称为服务器游标。ODBC和ADO定义了 Microsoft SQL Server 支持的4种游标类型,这样就可以为T_SQL游标指定4种游标类型。SQL Server支持的4种API服务器游标的类型是:(i).只进游标只进游标不支持滚动,它只支持游标从头到尾顺序提取。行只在从数据库中提取出来后才能检索。对所有又当前用户发出或又其它用户提交、并影响结果集中的行的INSERT,UPDATE和DELETE语句,其效果在这些行从游标中提取是可见的。由于游标无法向后滚动,则在提取行后对数据库中的行进行的大多数更改通过游标均不可见。当值用于确定所修改的结果集(例如更新聚集索引涵盖的列)中行的位置时,修改后的值通过游标可见。(ii).静态游标SQL Server静态游标始终是只读的。其完整结果集在打开游标时建立在tempdb中,静态游标总是按照打开游标时的原样显示结果集。游标不反映在数据库中所做的任何影响结果集成员身份的更改,也不反映对组合成结果集的行的列值所做的更改,静态游标不会显示打开游标以后在数据库中新插入的行,即使这些行符合游标SELECT语句的搜索条件。如果组成结果集的行被其它用户更新,则新的数据值不会显示在静态游标中。静态游标会显示打开游标以后从数据中删除的行。静态游标中不反UPDATE、INSERT或者DELETE操作(除非关闭游标然后重新打开),甚至不反映使用打开游标的同一连接所做的修改。(iii).由键驱动的游标该游标中各行的成员身份和顺序是固定的。由键集驱动的游标由一组唯一标识符(键)控制,这组键成为键集。键是根据以唯一方式标识结果集各行的一组列生成的,键集是打开游标时来自符合SELECT语句要求的所有行中的一组键值。由键集驱动的游标对应的键集是打开游标时在tempdb中生成的。(IV).动态游标动态游标与静态游标相对。当滚动游标时,动态游标反映结果集中所做的所有更改。结果集中的行数据值、顺序和成员在每次提取时都会改变。所有用户做的全部UPDATE、INSERT和DELETE语句均通过游标可见。如果使用API函数(如SQLSePos)或T_SQL WHERE CURRENT OF 子句通过游标进行更新,它们将立即可见。在游标外部所做的更新直到提交时才可见,除非将游标的事物隔离级别设为未提交读。二:游标的基本操作1.声明游标游标主要包括游标结果集和游标位置两部分,游标结果集是定义游标的SELECT语句返回的行集合,游标位置则是指向这个结果集中的某一行的指针。使用游标之前,要声明游标,SQL Server中声明使用DECLARE CURSOR语句,声明游标包括定义游标的滚动行为和用户生成游标所操作的结果集的查询,其语法格式如下:1234567DECLARE cursor_name CURSOR [ LOCAL | GLOBAL][ FORWARD_ONLY | SCROLL ][ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ][ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ][ TYPE_WARNING ] FOR select_statement[ FOR UPDATE [ OF column_name [,...n] ] ]cursor_name:是所定义的T_SQL 服务器游标的名称。LOCAL:对于在其中创建批处理、存储过程或触发器来说,该游标的作用域是局部的。GLOBAL:指定该游标的作用域是全局的FORWARD_ONLY:指定游标只能从第一行滚动到最后一行。FETCH NEXT是唯一支持的提取选项,如果在指定FORWARD_ONLY时不指定STATIC,KEYSET和DYNAMIC关键字,则游标作为DYNAMIC游标进行操作,如果FORWARD_ONLY和SCROLL均为指定,则除非指定STATIC,KEYSET和DYNAMIC关键字,否则默认为FORWARD_ONLY。STATIC,KEYSET和DYNAMIC游标默认为SCROLL。与ODBC和ADO这类数据库API不同,STATIC,KEYSET和DYNAMIC T_SQL游标支持FORWARD_ONLY。STATIC:定义一个游标,以创建将又该游标使用的数据临时复本,对游标的所有请求都从tempdb中的这以临时表中不得到应答;因此,在对该游标进行提取操作时返回的数据中不反映对基表所做的修改,并且该游标不允许修改。KEYSET:指定当游标打开时,游标重的行的成员身份和顺序已经固定。对行进行唯一标识的键值内置在tempdb内一个称为keyset的表中。DYNAMIC:定义一个游标,以反映在滚动游标时对结果集内的各行所做的所有数据更改。行的数据值、顺序和成员身份在每次提取时都会更改,动态游标不支持ABSOLUTE提取选项。FAST_FORWARD:指定启动了性能优化的FORWARD_ONLY、READ_ONLY游标。如果指定了SCROLL或FOR_UPDATE,则不能指定FAST_FORWARD。SCROLL_LOCKS:指定通过游标进行的定位更新或删除一定会成功。将行读入游标时SQL Server将锁定这些行,以确保随后可对它们进行修改,如果还指定了FAST_FORWARD或STATIC,则不能指定SCROLL_LOCKS。OPTIMISTIC:指定如果行自读入游标以来已得到更新,则通过游标进行的定位更新或定位删除不成功。当将行读入游标时,SQL Server不锁定行,它改用timestamp列值比较结果来确定行读入游标后是否发生了修改,如果表不包含timestamp列,它改用校验和值进行确定,如果以修改该行,则尝试进行的定位更新或删除将失败,如果还指定了FAST_FORWARD,则不能指定OPTIMISTIC。TYPE_WARNING:指定游标从所请求的类型隐式转换为另一种类型时,向客户端发送警告消息。select_statement:是定义游标结果集中的标准SELECT语句。【例】声明名称为cursor_fruit的游标1234USE sample_db;GODECLARE cursor_fruit CURSOR FORSELECT f_name,f_price FROM fruits;2.打开游标在使用游标之前必须先打开游标,打开游标的语法如下:OPEN [ GLOBAL ] cursor_name | cursor_variable_name;GLOBAL:指定cursor_name是全局游标。cursor_name:已声明的游标的名称。如果全局游标和局部游标都使用cursor_name作为其名称,那么如果指定了GLOBAL,则cursor_name指的是全局游标,否则cursor_name指的是局部游标。cursor_variable_name:游标变量的名称。【例】打开上例声明的名称为cursor_fruit的游标 123USE sample_db;GOOPEN cursor_fruit;3.读取游标中的数据打开游标之后就可以读取游标中的数据了,FETCH命令可以读取游标中的某一行数据。FETCH的语法如下:1234567891011ETCH [ [ NEXT | PRIOR | FIRST | LAST | ABSOLUTE { n | @nvar } | RELATIVE { n | @nvar } ]FROM]{ { [GLOBAL ] cursor_name } | @cursor_variable_name}[ INTO @variable_name [ ,...n ] ]NEXT:紧跟当前行返回结果行,并且当前行递增为返回行,如果FETCH NEXT为对游标的第一次提取操作,则返回结果集中的第一行。NEXT为默认的游标提取选项。PRIOR:返回紧邻当前行前面的结果行,并且当前行递减为返回行,如果FETCH PRIOR为对游标的第一次提取操作,则没有行返回并且游标置于第一行之前。FIRST:返回游标中的第一行并将其作为当前行。LAST:返回游标中的最后一行并将其作为当前行。ABSOLUTE { n | @nvar }:如果n或@nvar为正,则返回从游标头开始向后n行的第n行,并将返回行变成新的当前行。如果n或@nvar为负,则返回从游标末尾开始向前的n行的第n行,并将返回行变成新的当前行。如果n或@nvar为0,则不返回行。n必须是整数常量,并且@nvar的数据类型必须为int、tinyint或smallint.RELATIVE { n | @nvar }:如果n或@nvar为正,则返回从当前行开始向后的第n行。如果n或@nvar为负,则返回从当前行开始向前的第n行。如果n或@nvar为0,则返回当前行,对游标第一次提取时,如果在将n或@nvar设置为负数或0的情况下指定FETCH RELATIVE,则不返回行,n必须是整数常量,@nvar的数据类型必须是int、tinyint或smallint.GLOBAL:指定cursor_name是全局游标。cursor_name:已声明的游标的名称。如果全局游标和局部游标都使用cursor_name作为其名称,那么如果指定了GLOBAL,则cursor_name指的是全局游标,否则cursor_name指的是局部游标。@cursor_variable_name:游标变量名,引用要从中进行提取操作的打开的游标。INTO @variable_name [ ,...n ]:允许将提取操作的列数据放到局部变量中。列表中的各个变量从左到右与游标结果集中的相应列相关联。各变量的数据类型必须与相应的结果集列的数据类型相匹配,或是结果集列数据类型所支持的隐士转换。变量的数目必须与游标选择列表中的列数一致。【例】使用名称为cursor_fruit的光标,检索fruits表中的记录,输入如下: 1234567891011ETCH [ [ NEXT | PRIOR | FIRST | LAST | ABSOLUTE { n | @nvar } | RELATIVE { n | @nvar } ]FROM]{ { [GLOBAL ] cursor_name } | @cursor_variable_name}[ INTO @variable_name [ ,...n ] ]4.关闭游标SQL Server 在打开游标之后,服务器会专门为游标开辟一定的内存空间存放游标操作的数据结果集,同时游标的使用也会根据具体情况对某些数据进行封锁。所以在不使用游标的时候,可以将其关闭,以释放游标所占用的服务器资源,关闭游标使用CLOSE语句。语法格式如下: CLOSE [ GLOBAL ] cursor_name | cursor_variable_name【例】关闭名称为cursor_fruit的游标CLOSE cursor_fruit; 5.释放游标游标操作的结果集空间虽然被释放了,但是游标本身也会占用一定的计算集资源,所以使用完游标之后,为了收回被游标占用的资源,应该将游标释放。释放游标使用DEALLOCATE语句,语法格式如下:DEALLOCATE [GLOBAL] cursor_name | @ccursor_variable_name@ccursor_variable_name:游标变量的名称,@ccursor_variable_name必须为cursor类型。DEALLOCATE @ccursor_variable_name 语句只删除对游标变量名称的引用,直到批处理、存储过程或触发器结束时变量离开作用域,才释放变量。【例】使用DEALLOCATE语句释放名称为cursor_fruit的变量,输入如下:DEALLOCATE cursor_fruit;三:游标的运用1.使用游标变量声明变量用DECLARE,为变量赋值可以用set或SELECT语句,对于游标变量的声明和赋值,其操作基本相同。在具体使用时,首先要创建一个游标,将其打开后,将游标的值赋给游标变量,并通过FETCH语句从游标变量中读取值,最后关闭释放游标。【例】声明名称为@varCursor的游标变量,输入如下:123456789101112DECLARE @varCursor Cursor --声明游标变量DECLARE cursor_fruit CURSOR FOR --创建游标SELECT f_name,f_price FROM fruits;OPEN cursor_fruit --打开游标SET @varCursor=cursor_fruit --为游标变量赋值FETCH NEXT FROM @varCursor --从游标变量中读取值WHILE @@FETCH_STATUS=0 --判断FETCH语句是否执行成功BEGINFETCH NEXT FROM @varCursor --读取游标变量中的数据ENDCLOSE @varCursor --关闭游标DEALLOCATE @varCursor; --释放游标复制2.用游标为变量赋值在游标的操作过程中,可以使用FETCH语句将数据值存入变量,这些保持表中列值的变量可以在后面的程序中使用。【例】创建游标cursor_variable,将fruits表中的记录f_name,f_price值赋给变量@fruitName和@fruitPrice,并打印输出。3.用ORDER BY 子句改变游标中的执行顺序游标是一个查询结果集,那么能不能对结果进行排序呢?答案是否定的。与基本的SELECT语句中的排序方法相同,ORDER BY子句添加到查询中可以对游标查询的结果排序。 注意:只有出现在游标中的SELECT语句中的列才能作为ORDER BY 子句的排序列,而对与非游标的SELECT语句中,表中任何列都可以作为ORDER BY 的排序列,即使该列没有出现在SELECT语句的查询结果列中。4.用游标修改数据【例】声明整型变量@sid=101,然后声明一个对fruits表进行操作的游标,打开该游标,使用FETCH NEXT方法来获取游标中的每一行的数据,如果获取到的记录的s_id的字段值与@sid值相同,将s_id=@sid的记录中的f_price修改为12.
-
SQL Server并不提供trim()函数去除字符串两边空格,只提供了去除字符串左边空格ltrim()函数和去除右边字符串空格rtrim()函数,但是只要将这两个函数配合使用,就能达到去除字符串两端空格的效果。ltrim()函数的使用:1select ltrim(' aa ')去除item_no字段内左边的空格:123update t_bd_item_info20231115set item_no = ltrim(item_no)where item_subno = '0002'rtrim()函数的使用:1select ltrim(' aa ')去除item_no字段内右边的空格:123update t_bd_item_info20231115set item_no = rtrim(item_no)where item_subno = '0002'ltrim()函数和rtrim()函数配合使用:1select rtrim(ltrim(' aa '))去除item_no字段内左边右边的空格:123update t_bd_item_info20231115set item_no = rtrim(ltrim(item_no))where item_subno = '0002'复制也可以用replace()函数来去除所有空格:1select replace(' aa ',' ','')去除item_no字段内左边右边的空格:123update t_bd_item_info20231115set item_no = replace(item_no,' ','')where item_subno = '0002'
-
一、概述 1.1 角色和用户 PostgreSQL 使用角色的概念管理数据库访问权限。角色是一系列相关权限的集合。为了管理方便,通常把一系列相关的数据库权限赋给一个角色,如果哪个用户需要这些权限,就把角色赋给相应的用户。由于用户也拥有一系列的相关权限,为了简化管理,在 PostgreSQL 中,角色与用户是没有区别的,一个用户也是一个角色,我们可以把一个用户的权限赋给另一个用户。 用户和角色在整个数据库实例中是全局的,在同一个实例中的不同数据库中,看到的用户都是相同的。在初始化数据库系统时有一个预定义的超级用户,这个用户的名称与初始化该数据库的操作系统用户名相同。如果数据库是建在操作系统用户“postgres”(通常我们把数据库安装在此用户下)下的,那么这个数据库超级用户的名称也叫“postgres”。可以用这个超级用户连接数据库,然后创建出更多的普通用户或其他超级用户。 在 SQL 标准中,用户和角色之间的区别很清楚,并且用户不会自动继承权限而角色会继承。这种行为在 PostgreSQL 中也可以实现:为要用作 SQL 角色的角色给予 INHERIT 属性,而为要用作 SQL 用户的角色给予 NOINHERIT 属性。不过,为了向后兼容 8.1 以前的发布(在其中用户总是拥有它们所在组的权限),PostgreSQL 默认给所有的角色 INHERIT 属性。 1.2 用户和用户组 PostgreSQL 可以把用户分组在一起,权限可以被授予一整个组或从一整个组回收。一旦组角色存在,可以使用 GRANT 和 REVOKE 命令增加和移除成员: GRANT group_role TO role1, ... ; REVOKE group_role FROM role1, ... ; 1 2 注意事项: 一个用户可以是多个组的成员。 不允许环状的成员关系。 不允许把一个用户授予给 PUBLIC。 1.3 PUBLIC 角色 PUBLIC 是 PostgreSQL 数据库中一个特殊的角色组,在元数据表(pg_roles)中都查不到该角色,数据库中所创建的角色都可以理解为是 PUBLIC 角色组成员。而且对 PUBLIC 权限的继承完全不受 NOINHERIT 的控制,一旦创建了一个拥有 login 权限的角色,它会立即继承 PUBLIC 角色组拥有的权限,此时如果想通过 revoke(比如 revoke connect on database)来回收的话不会成功,只能从 PUBLIC 组回收相关权限(比如 revoke connect on database from PUBLIC)。 PUBLIC 默认权限 数据库的 connect,temp/temprary 权限。任何新建的数据库,系统会自动为 PUBLIC 角色赋予connect 和在任何 schema 下创建临时表的权限。 public 模式的 usage,create 权限。在任何新建的数据库的 public 模式下有 usage 和 create 的权限。 函数的 execute 权限(仅限于 public 模式下)。 语言和数据类型(包括域)的 usage 权限。 二、权限授予 在 PostgreSQL 数据库中,每个数据库对象都有一个所有者(owner),对于大部分类型的对象,默认只有其所有者和超级用户(管理员用户)能够对该对象做任何事情。为了允许其他角色使用它,必须分配对应的权限。 根据 PostgreSQL 数据库的逻辑结构:实例(集簇)->数据库->schema->数据库对象,可将其权限分为如下几类: 实例权限:由 postgresql.conf,pg_hba.conf 文件控制,控制哪些用户哪些IP以哪种方式连接数据库。 数据库权限:是否允许连接数据库,是否允许在数据库中创建模式(schema)。 模式权限:是否允许查看模式中的对象,是否允许在模式下建表。 对象权限:对表来说就是增删改查,对函数来说就是执行,修改等。 系统权限:也可以称为角色属性,即创建用户时,自身携带的一些权限。 2.1 实例权限 https://xiaosonggong.blog.csdn.net/article/details/124264877 2.2 数据库权限 为已创建用户授权数据库操作权限。 grant {{create|connect|temporary|temp}|all[ privileges]} on database 数据库名 to 用户名|pubilc [with grant option]; 1 参数说明: create:对于数据库,允许在数据库中创建新的schema、table、index。 connect:允许用户连接到指定的数据库。在连接启动时检查此权限。 temporary、temp:允许在使用指定数据库时创建临时表。 all privileges:一次授予所有可用权限。 public:所有用户。 2.3 模式权限 为已创建用户授权模式操作权限。 grant {{create|usage}|all [privileges]} on schema 模式名 to 用户名|pubilc [with grant option]; 1 参数说明: create:对于schema,允许在模式中创建新的 table、index等。 usage:对于schema,允许访问指定模式中包含的对象;对于 sequence,允许使用 currval 和nextval 函数。对于类型和域,允许在创建表,函数和其他模式对象时使用类型或域。 all privileges:一次授予所有可用权限。 public:所有用户。 2.4 对象权限 为已创建用户授权基本对象操作权限。 grant {{select|insert|update|delete|truncate|references|trigger}|all [privileges]} on {[table] 表名|all tables in schema 模式名} to 用户名|pubilc [with grant option]; 1 参数说明: select:允许从指定表,视图或序列的任何列或列出的特定列进行 select。也允许使用 copy to。在 update 或 delete 中引用现有列值也需要此权限。对于序列,此权限还允许使用 currval函数。对于大对象,此权限允许读取对象。 insert:允许将新行 insert 到指定的表中。如果列出了特定列,则只能在 insert 命令中为这些列分配(因此其他列将接收默认值)。也允许 copy from。 update:允许更新指定表的任何列或列出的特定列,需要 select 权限。 delete:允许删除指定表中的行,需要 select 权限。 truncate:允许清空指定表。 references:允许创建引用指定表或表的指定列的外键约束。 trigger:允许在指定的表上创建触发器。 execute:允许使用指定的函数或过程以及在函数。 all privileges:一次授予所有可用权限。 public:所有用户。 2.5 系统权限 创建用户时携带属性,创建后也可使用 alter 进行修改。create user 是 create role 的一个别名。唯一的区别是 create user 中 login 被作为默认值,而 create role 中 nologin 是默认值。 create user/role 用户名|public [with] option; alter user/role 用户名|public [with] option; 1 2 option 可以为 superuser|nosuperuser:超级权限,拥有所有权限,默认 nosuperuser。 inherit|noinherit:继承权限,可以把除superuser权限继承给其他用户/角色,默认 inherit。 login|nologin:登录权限,作为连接的用户,默认 nologin,除非是 create user(默认登录)。 password ‘password’|null:设置密码,密码仅用于有 login 属性的用户,不使用密码身份验证,则可以省略此选项,可以选择将空密码显式写为password null。 valid until ‘timestamp’:密码有效期时间,不设置则用不失效。 createdb|nocreatedb:建库权限,默认 nocreatedb。 createrole|nocreaterole:建角色权限,拥有创建、修改、删除角色,默认nocreaterole。 replication|noreplication:复制权限,用于物理或则逻辑复制(复制和删除 slots),默认是 noreplication。 bypassrls|nobypassrls:安全策略rls权限,默认nobypassrls。 connection limit connlimit:限制用户并发数,默认-1,不限制。正常连接会受限制,后台连接和prepared事务不受限制。 public:所有用户。 三、权限查看 3.1 权限查看 --数据库权限查看 postgres=# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+-------------+-------------+----------------------- appdb | appuser | UTF8 | en_US.UTF-8 | en_US.UTF-8 | d1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =Tc/postgres + | | | | | postgres=CTc/postgres+ | | | | | u1=c/postgres postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres (5 rows) --模式权限查看 postgres=# \dn+ List of schemas Name | Owner | Access privileges | Description --------+----------+----------------------+------------------------ public | postgres | postgres=UC/postgres+| standard public schema | | =UC/postgres | sch1 | postgres | | (2 rows) --对象权限查看 d1=> select * from information_schema.table_privileges where grantee = 'u1'; grantor | grantee | table_catalog | table_schema | table_name | privilege_type | is_grantable | with_hierarchy ---------+---------+---------------+--------------+------------+----------------+--------------+---------------- u1 | u1 | d1 | d1s1 | t1 | INSERT | YES | NO u1 | u1 | d1 | d1s1 | t1 | SELECT | YES | YES u1 | u1 | d1 | d1s1 | t1 | UPDATE | YES | NO u1 | u1 | d1 | d1s1 | t1 | DELETE | YES | NO u1 | u1 | d1 | d1s1 | t1 | TRUNCATE | YES | NO u1 | u1 | d1 | d1s1 | t1 | REFERENCES | YES | NO u1 | u1 | d1 | d1s1 | t1 | TRIGGER | YES | NO (7 rows) --系统权限查看 d1=> select * from pg_roles; rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | rolbypassrls | rolconfig | oid ---------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+---------------+--------------+-----------+------- pg_signal_backend | f | t | f | f | f | f | -1 | ******** | | f | | 4200 pg_read_server_files | f | t | f | f | f | f | -1 | ******** | | f | | 4569 postgres | t | t | t | t | t | t | -1 | ******** | | t | | 10 pg_write_server_files | f | t | f | f | f | f | -1 | ******** | | f | | 4570 pg_execute_server_program | f | t | f | f | f | f | -1 | ******** | | f | | 4571 pg_read_all_stats | f | t | f | f | f | f | -1 | ******** | | f | | 3375 pg_monitor | f | t | f | f | f | f | -1 | ******** | | f | | 3373 syd | f | t | f | f | t | f | -1 | ******** | | f | | 16387 u1 | f | t | f | f | t | f | -1 | ******** | | f | | 41008 pg_read_all_settings | f | t | f | f | f | f | -1 | ******** | | f | | 3374 pg_stat_scan_tables | f | t | f | f | f | f | -1 | ******** | | f | | 3377 u2 | f | t | f | f | t | f | -1 | ******** | | f | | 41009 repmgr | t | t | f | f | t | f | -1 | ******** | | f | | 32769 (13 rows) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 3.2 ACL 格式说明 上述数据库及模式权限均显示为 ACL(访问控制列表)缩写,显示格式为: 接受赋权的用户(省略时表示 PUBLIC 角色组)= 授予的权限/授予的用户 1 授予的权限具体含义如下: 权限 缩写 适用对象类型 SELECT r LARGE OBJECT, SEQUENCE, TABLE (and table-like objects), table column INSERT a TABLE, table column UPDATE w LARGE OBJECT, SEQUENCE, TABLE, table column DELETE d TABLE TRUNCATE D TABLE REFERENCES x TABLE, table column TRIGGER t TABLE CREATE C DATABASE, SCHEMA, TABLESPACE CONNECT c DATABASE TEMPORARY T DATABASE EXECUTE X FUNCTION, PROCEDURE USAGE U DOMAIN, FOREIGN DATA WRAPPER, FOREIGN SERVER, LANGUAGE, SCHEMA, SEQUENCE, TYPE 访问权限摘要: 对象类型 所有权限 默认 PUBLIC 权限 psql 命令 DATABASE CTc Tc \l DOMAIN U U \dD+ FUNCTION or PROCEDURE X X \df+ FOREIGN DATA WRAPPER U none \dew+ FOREIGN SERVER U none \des+ LANGUAGE U U \dL+ LARGE OBJECT rw none none SCHEMA UC none \dn+ SEQUENCE rwU none \dp TABLE (and table-like objects) arwdDxt none \dp Table column arwx none \dp TABLESPACE C none \db+ TYPE U U \dT+ 四、撤销权限 上述所有通过 grant 方式授予的权限,均可通过列语法撤销。 revoke [grant option for] {上述所有权限} from {用户名|public} [cascade|restrict]; 1 public:所有用户。 cascade:级联回收权限。 restrict:不级联回收权限。 五、默认权限修改 5.1 概述 ALTER DEFAULT PRIVILEGES 允许设置将被应用于未来要创建的对象的特权(它不会影响分配给已经存在的对象的特权)。当前,只能修改用于模式、表(包括视图和外部表)、序列、函数和类型(包括域)的特权。其中,可设置权限的函数包括聚集函数和过程函数。当这个命令应用于函数时,单词 FUNCTIONS 和 ROUTINES 是等效的。(推荐使用 ROUTINES,因为它是用来囊括函数和过程的一个标准术语。在较早的 PostgreSQL 发行版中,只允许单词 FUNCTIONS。无法为函数或过程单独设置默认特权。)只能改变你自己或者你属于其中的角色所创建的对象的默认特权。这些特权可以对全局范围设置(即对当前数据库中创建的所有对象),或者只对在指定模式中创建的对象设置。 5.2 语法 ALTER DEFAULT PRIVILEGES [ FOR { ROLE | USER } target_role [, ...] ] [ IN SCHEMA schema_name [, ...] ] abbreviated_grant_or_revoke 其中abbreviated_grant_or_revoke是下列之一: GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } [, ...] | ALL [ PRIVILEGES ] } ON TABLES TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { { USAGE | SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON SEQUENCES TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { EXECUTE | ALL [ PRIVILEGES ] } ON { FUNCTIONS | ROUTINES } TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { USAGE | ALL [ PRIVILEGES ] } ON TYPES TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] GRANT { USAGE | CREATE | ALL [ PRIVILEGES ] } ON SCHEMAS TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] REVOKE [ GRANT OPTION FOR ] { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } [, ...] | ALL [ PRIVILEGES ] } ON TABLES FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { { USAGE | SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON SEQUENCES FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { EXECUTE | ALL [ PRIVILEGES ] } ON { FUNCTIONS | ROUTINES } FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | ALL [ PRIVILEGES ] } ON TYPES FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] { USAGE | CREATE | ALL [ PRIVILEGES ] } ON SCHEMAS FROM { [ GROUP ] role_name | PUBLIC } [, ...] [ CASCADE | RESTRICT ] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 参数说明: target_role:一个现有角色的名称,当前角色是它的一个成员。如果 FOR ROLE 被忽略,将假定为当前角色。 schema_name:一个现有模式的名称。如果被指定,以后在那个模式中创建的对象的默认特权会被修改。如果 IN SCHEMA 被忽略,全局默认特权会被修改。 当设置特权给模式时不能使用 IN SCHEMA,因为模式不能嵌套。 role_name:要为其授予或者收回特权的一个现有角色的名称。这个参数以及所有 abbreviated_grant_or_revoke 中的其他参数会按照 GRANT 或者 REVOKE 中描述的方式运作,不过这里是为一整类的对象而不是特别指定的对象设置权限。 六、示例 6.1 创建只读用户 创建 readonly 用户,只可查询 test 模式下的表,连入对应数据库执行如下操作。 --创建只读用户 create user readonly with password 'postgres'; --将 schema 中 usage 权限赋予给 readonly 用户,访问所有已存在的表 grant usage on schema test to readonly; grant select on all tables in schema test to readonly; --未来访问 test 模式下所有新建的表 alter default privileges in schema test grant select on tables to readonly ; 1 2 3 4 5 6 7 8 9 6.2 删除只读用户 修改过默认特权的用户要进行删除,均先删除修改的默认特权后在进行删除用户操作 --删除授予的默认特权 drop owned by readonly; --删除用户 drop user readonly; 1 2 3 4 5 七、补充默认角色 PostgreSQL提供了一组默认角色,它们提供对特定的、通常需要的、需要特权的功能和信息的访问。管理员可以把这些角色GRANT给其环境中的用户或者其他角色,让这些用户能够访问指定的功能和信息。在授予这些角色时应当非常小心,以确保它们只被用在需要的地方。 角色 允许的访问 pg_read_all_settings 读取所有配置变量,甚至是那些通常只对超级用户可见的变量。 pg_read_all_stats 读取所有的 pg_stat_* 视图并且使用与扩展相关的各种统计信息,甚至是那些通常只对超级用户可见的信息。 pg_stat_scan_tables 执行可能会在表上取得ACCESS SHARE锁的监控函数(可能会持锁很长时间)。 pg_monitor 读取/执行各种不同的监控视图和函数。这角色是pg_read_all_settings,pg_read_all_stats和pg_stat_scan_tables的成员。 pg_signal_backend 发信号到其他后端以取消查询或中止它的会话。 pg_read_server_files 允许使用COPY以及其他文件访问函数从服务器上该数据库可访问的任意位置读取文件。 pg_write_server_files 允许使用COPY以及其他文件访问函数在服务器上该数据库可访问的任意位置中写入文件。 pg_execute_server_program 允许用运行该数据库的用户执行数据库服务器上的程序来配合COPY和其他允许执行服务器端程序的函数。 ———————————————— 版权声明:本文为CSDN博主「脑子进水养啥鱼?」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/songyundong1993/article/details/131771107
-
前言 上文我们介绍了maven的setting文件。今天我们来总结一下,maven中另一个重要文件,pom文件。 什么是POM文件? POM(Project Object Model)文件是Maven项目的核心文件之一。它是一个XML文件,描述了项目的基本信息、依赖项、构建和发布等信息。POM文件是Maven的重要组成部分,可以帮助开发者管理和构建项目。在使用Maven进行项目构建时,需要根据项目的需要配置POM文件。 POM文件的基本结构 POM文件是一个XML文件,包含多个元素,每个元素代表一个特定的配置项。下面是一个POM文件的基本结构: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>example-project</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- 依赖项配置 --> </dependencies> <build> <!-- 构建配置 --> </build> <repositories> <!-- 仓库配置 --> </repositories> </project> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 POM文件的根元素是·<project>,它包含了多个子元素。其中<modelVersion>元素指定了POM文件的版本,通常设置为4.0.0。<groupId>、<artifactId>和<version>元素是必需的,它们用于定义项目的坐标信息。<dependencies>、<build>和<repositories>元素用于配置依赖项、构建和仓库信息。 POM文件的常用配置项 1. 坐标信息 坐标信息指的是<groupId>、<artifactId>和<version>元素。<groupId>定义了项目的组织ID,<artifactId>定义了项目的唯一标识符,<version>定义了项目的版本号。这些信息对于Maven的依赖管理和构建过程非常重要。 <groupId>com.example</groupId> <artifactId>example-project</artifactId> <version>1.0-SNAPSHOT</version> 1 2 3 2. 依赖项配置 依赖项配置用于定义项目所依赖的外部库。Maven会自动下载并管理这些依赖项。依赖项配置包含在<dependencies>元素中,每个依赖项使用一个<dependency>元素进行描述。 <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.3.13</version> </dependency> </dependencies> 1 2 3 4 5 6 7 3.构建配置 构建配置用于定义项目的构建过程。它包含在<build>元素中,包括了多个子元素。其中比较常用的子元素有: <build> <plugins> <!-- 插件配置 --> </plugins> <resources> <!-- 资源文件配置 --> </resources> <testResources> <!-- 测试资源文件配置 --> </testResources> </build> 1 2 3 4 5 6 7 8 9 10 11 4. 插件配置 插件是Maven的一个重要特性,它可以用于扩展Maven的功能。Maven自带了一些插件,比如maven-compiler-plugin、maven-jar-plugin等。插件配置包含在<plugins>元素中,每个插件使用一个<plugin>元素进行描述。 <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> 1 2 3 4 5 6 7 8 9 10 11 5. 仓库配置 仓库配置用于定义Maven的依赖项下载地址。Maven默认使用中央仓库,但是也可以配置私有仓库或者本地仓库。仓库配置包含在<repositories>元素中,每个仓库使用一个<repository>元素进行描述。 <repositories> <repository> <id>central</id> <url>https://repo.maven.apache.org/maven2</url> </repository> </repositories> 1 2 3 4 5 6 父子pom 父子POM是Maven中一个重要的概念。在Maven项目中,我们通常会使用父子POM的方式来管理项目的依赖、构建和打包方式等。 父POM 父POM是指一个Maven项目中的顶层POM文件。父POM文件可以被多个子模块所继承,子模块可以继承父POM中的配置信息。在父POM中通常包含一些基本的配置信息,如项目的坐标、开发者信息、构建配置等。父POM文件通常被命名为pom.xml,并且不包含任何代码。 <project> <modelVersion>4.0.0</modelVersion> <groupId>com.example.parent</groupId> <artifactId>parent</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <modules> <module>child1</module> <module>child2</module> </modules> <dependencies> <!-- 依赖配置 --> </dependencies> <build> <!-- 构建配置 --> </build> </project> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 子POM 子POM是指一个Maven项目中的子模块POM文件。子模块可以继承父POM中的配置信息,同时也可以覆盖或者新增一些配置信息。子模块POM文件通常包含项目的代码、测试代码、资源文件等信息。子POM文件的命名通常是根据项目的名称来命名的,比如example-web、example-service等。 <project> <parent> <groupId>com.example.parent</groupId> <artifactId>parent</artifactId> <version>1.0.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>child1</artifactId> <packaging>jar</packaging> <dependencies> <!-- 依赖配置 --> </dependencies> <build> <!-- 构建配置 --> </build> </project> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 父子POM的优点 继承:父POM中的配置信息可以被子模块所继承,这样可以避免重复配置,提高配置的可维护性。 一致性:通过父POM可以统一管理子模块的依赖、构建和打包方式等,保证各个子模块之间的一致性。 可扩展性:在父POM中定义一些通用的配置信息,可以为后续的新子模块提供一些默认配置,提高了可扩展性。 父子POM的使用 在Maven项目中使用父子POM的方式很简单,只需要在子模块的POM文件中声明父POM即可。 <project> <parent> <groupId>com.example.parent</groupId> <artifactId>parent</artifactId> <version>1.0.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>child1</artifactId> <packaging>jar</packaging> <dependencies> <!-- 依赖配置 --> </dependencies> <build> <!-- 构建配置 --> </build> </project> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 在上面的例子中,子模块child1的POM文件中声明了父POM文件的信息,包括groupId、artifactId和version。 在实际开发中,通常会将父POM文件和子模块的POM文件分开管理,并将父POM文件上传到Maven仓库中。 这样其他开发者在开发新的子模块时就可以使用已有的父POM文件,避免重复配置,提高了开发效率。 总结 POM文件是Maven项目的核心文件之一,它包含了Maven项目的所有配置信息。 父子POM是Maven中一个重要的概念,使用父子POM的方式可以提高项目的可维护性、一致性和可扩展性。 在实际开发中,我们可以将父POM文件上传到Maven仓库中,方便其他开发者使用。 我们的项目里就使用了nexus和maven进行了父子控制,在子项目中指定父项目,父子项目分开管理。 ———————————————— 版权声明:本文为CSDN博主「郝老三」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/hlzdbk/article/details/129827535
-
一.简单介绍 1.介绍 Nginx(发音为"engine x")是一款高性能、轻量级的开源 Web 服务器和反向代理服务器,它具有以下特点和功能: 高性能:Nginx 被设计为能够处理大量并发连接而不显著增加系统负担。它采用异步事件驱动的架构,可以有效地处理高流量的 Web 请求。 负载均衡:Nginx 支持负载均衡,可以将请求分发到多个后端服务器,以提高网站性能和可用性。 反向代理:Nginx 可以充当反向代理,将客户端请求转发到后端服务器,隐藏后端服务器的真实 IP 地址,增加安全性和可扩展性。 静态文件服务:Nginx 可以高效地提供静态文件(如 HTML、CSS、JavaScript、图像等)的服务,减轻应用服务器的负担。 SSL/TLS 支持:Nginx 支持加密通信,可以配置 SSL/TLS 来保护数据传输的安全性。 URL 重写:Nginx 允许对 URL 进行灵活的重写和转发,以实现友好的 URL 结构和路由。 缓存:Nginx 可以缓存静态内容和动态内容,提高响应速度并减轻后端服务器的负担。 访问控制:Nginx 可以实施访问控制、IP 黑名单、基本身份验证等安全性措施。 模块化架构:Nginx 使用模块化的架构,允许用户通过插件和模块来扩展其功能。 Nginx 通常被用于构建高性能的 Web 服务器环境,特别适合处理大流量的网站和应用。它在互联网上广泛使用,并已成为许多大型网站和应用的关键组件之一。 2.功能 以下是 Nginx 的一些主要功能: Web 服务器: Nginx 可以作为一个快速、高性能的 Web 服务器,可以直接处理和提供静态和动态内容。 反向代理: Nginx 可以作为反向代理服务器,接收客户端请求并将其转发到后端服务器,用于负载均衡、缓存、SSL 终端等。 负载均衡: Nginx 可以将来自客户端的请求分发到多个后端服务器,实现负载均衡,提高应用的可扩展性和性能。 HTTP 缓存: Nginx 可以缓存静态和动态内容,减轻后端服务器的负载,提高响应速度。 SSL 终端: Nginx 可以处理 SSL/TLS 连接,用于终止和处理加密通信,减轻后端服务器的计算负担。 反向代理缓存: Nginx 可以作为反向代理缓存,将动态内容缓存到本地,减少对后端服务器的请求,提高响应速度。 动态内容处理: Nginx 可以处理 FastCGI、uWSGI、SCGI 等协议,用于处理动态内容如 PHP、Python、Ruby 等。 限流和速率控制: Nginx 可以实施请求速率控制和限流,以防止服务器过载。 安全性: Nginx 提供安全功能如防止恶意请求、DDoS 攻击防护等。 虚拟主机: Nginx 支持虚拟主机配置,可以在一个服务器上托管多个域名。 自定义模块: Nginx 支持自定义模块开发,可以根据需求添加自定义的功能和扩展。 事件驱动: Nginx 使用事件驱动的异步架构,可以处理大量并发连接,提供出色的性能。 日志记录: Nginx 可以记录详细的访问日志,方便监控和分析。 Nginx 是一个功能强大的服务器软件,适用于多种应用场景,如 Web 服务器、反向代理、负载均衡、缓存、安全保护等。它在大型互联网公司和企业中被广泛使用,提供了高性能和稳定性。 3.安装步骤 #查看nginx在哪 whereis nginx #yum 安装ningx #nginx添加yum repro库中 #下载nginx包 wget https://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm # 建立nginx的yum仓库 rpm -ivh nginx-release-centos-7-0.el7.ngx.noarch.rpm #查看nginx的信息 yum info nginx #查看yum源仓库中nginx版本 yum --showduplicates list nginx | expand #安装nginx,默认安装最新的稳定版本 及 nginx 1.20.2 yum install nginx #查看版本 nginx -V #查看日志 tail -f /var/log/nginx/error.log #配置文件地址 /etc/nginx/nginx.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 二.常用命令 1.启动 nginx #查看nginx位置 whereis nginx #nginx可用 systemctl enable nginx #启动nginx systemctl start nginx #查看进程号 netstat -nltp #查看状态 systemctl status nginx 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2.停止 nginx #停止 nginx systemctl stop nginx 1 2 3.重启 nginx #重启 nginx systemctl restart nginx 1 2 4.重新加载配置 #重新加载配置 systemctl reload nginx 1 2 5.设置开机启动 #设置开机启动 systemctl enable nginx 1 2 6.关闭开机启动设置 #关闭开机启动设置 systemctl disable nginx 1 2 7.检查配置是否正确 #检查配置是否正确(常用) nginx -t 1 2 8.检查加载模块 ./nginx -V 1 9.重新加载 #进入nginx可执行目录sbin下,输入命令,不用重启 ./nginx -s reload 1 2 10.指定启动 #启动nginx,并挂在配置文件目录到宿主机 docker run -d --name deepexi-belle-damo-nginx --privileged=true --dns 114.114.114.114 -p 80:80 \ -v /etc/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf \ --restart=always deploy.deepexi.com/datasense-test/deepexi-belle-damo-nginx:v1.0.0 1 2 3 4 三.常见配置 Nginx 的主配置文件是 nginx.conf,这个配置文件一共由三部分组成,分别为全局块、events 块和 http 块。在 http 块中,又包含 http 全局块、多个 server 块。每个 server 块中,可以包含 server 全局块和多个 location 块。在同一配置块中嵌套的配置块,各个之间不存在次序关系。 1.配置目录 #从 / 根目录下查找文件名为 nginx.conf 的文件 find / -name nginx.conf #从/etc 目录下查找文件名为 nginx.conf 的文件 find /etc -name nginx.conf #检查配置文件 nginx -t #目录 /etc/nginx 1 2 3 4 5 6 7 8 9 10 11 2.执行目录 /usr/sbin/nginx 1 3.站点目录 /usr/share/nginx/html 1 4.我的 nginx 配置 server { listen 80; server_name qinyingjie.top; root /usr/share/nginx/html; include /etc/nginx/default.d/*.conf; location / { root html; index index.html index.htm; proxy_pass http://localhost:8080/; } location ~ .*\.(gif|jpg|jpeg|png|jfif)$ { root /kwan/; autoindex on ; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 = :用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求 ~ :用于表示 uri 包含正则表达式,并且区分大小写 ~* :用于表示 uri 包含正则表达式,并且不区分大小写 ^~ :用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求。字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 uri 和请求字符串做匹配。 5.服务器 43.139.90.182 qinyingjie.top 1 6.配置文件的优先级 启动时可以指定配置文件 首先,说明结论:同一目录下存在多个配置文件时,Nginx是按照文件的名称先后顺序依次读取的! #验证配置文件 /usr/local/nginx/sbin/nginx -tc /usr/local/nginx/conf/nginx.conf /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf #指定配置文件启动 /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf #指定配置文件重启 /usr/local/nginx/sbin/nginx -s reload -c /usr/local/nginx/conf/nginx.conf #说明:-c 参数指定运行nginx系统的自定义配置文件。 #若加:使用自定义配置文件。 #若不加:使用默认的nginx.conf(一般位于/usr/local/conf/nginx.conf,具体以实际情况为准) nginx -c /usr/local/nginx/conf/nginx.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 7.websocket 要在 Nginx 中开通 WebSocket,需要在 Nginx 配置文件中添加相应的配置。 以下是一个简单的 Nginx 配置文件示例,其中开通了 WebSocket: http { # ... map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; server_name example.com; location /ws/ { proxy_pass http://backend_server/ws/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 在这个配置文件中,map 指令用于将 HTTP 请求头中的 Upgrade 和 Connection 字段映射到 Nginx 的变量中,proxy_pass 指令用于将请求转发到后端服务器,proxy_http_version 指令用于指定使用 HTTP 1.1 协议进行转发,proxy_set_header 指令用于设置请求头字段。 具体来说,proxy_set_header Upgrade $http_upgrade; 指令用于将 HTTP 请求头中的 Upgrade 字段设置为 $http_upgrade 变量的值,proxy_set_header Connection $connection_upgrade; 指令用于将 HTTP 请求头中的 Connection 字段设置为 $connection_upgrade 变量的值。 这样,当客户端发送一个 WebSocket 请求时,Nginx 就会将其转发到后端服务器,并将请求头中的 Upgrade 和 Connection 字段设置为 WebSocket 需要的值,从而成功开通了 WebSocket。 四.牛逼特性 1.域名配置 upstream qinyingjie.top { server localhost:8080; } location / { proxy_pass https://www.qinyingjie.top; } 1 2 3 4 5 6 server_name qinyingjie.top; 1 2.图片不展示 location ~ .*\.(gif|jpg|jpeg|png|jfif)$ { proxy_pass https://www.qinyingjie.top; root /kwan/; autoindex on; } 1 2 3 4 5 3.负载均衡 1.轮训 upstream open-api-test-category{ server 10.250.16.111:8195; server 10.250.16.111:8196; } location / { proxy_pass http://open-api-test-category/; } 1 2 3 4 5 6 7 8 2.权重 upstream open-api-test-category{ server 10.250.16.111:8195 weight=1; server 10.250.16.111:8196 weight=3; } location / { proxy_pass http://open-api-test-category/; } 1 2 3 4 5 6 7 8 3.hash upstream open-api-test-category{ server 10.250.16.111:8195; server 10.250.16.111:8196; ip_hash; } location / { proxy_pass http://open-api-test-category/; } 1 2 3 4 5 6 7 8 9 4.动静分离 location ~ .*\.(gif|jpg|jpeg|png|jfif)$ { root /kwan/ ; autoindex on ; } 1 2 3 4 5.正向代理 正向代理是代理服务器位于客户端和目标服务器之间的一种代理方式。 客户端请求发送到正向代理服务器,然后由代理服务器将请求转发到目标服务器。 正向代理隐藏了客户端的真实 IP 地址,使目标服务器只能看到代理服务器的 IP 地址。 正向代理通常用于访问被封锁或受限制的内容,或者用于增加安全性和隐私。 比如 VPN,原理就是使用了正向代理,隐藏了客户端的信息。 6.反向代理 反向代理是代理服务器位于目标服务器和客户端之间的一种代理方式。 客户端将请求发送到反向代理服务器,然后代理服务器根据规则将请求转发给后端的目标服务器。 反向代理隐藏了目标服务器的真实 IP 地址,客户端只能看到代理服务器的 IP 地址。 反向代理通常用于负载均衡、缓存、安全性和高可用性方面,可以提高网站的性能和可靠性。 比如部署的服务,使用反向代理,隐藏服务端信息,避免被攻击。 location / { root html; index index.html index.htm; proxy_pass http://localhost:8080/; } 1 2 3 4 5 7.root 和 alias 区别 最基本的区别:alias 指定的目录是准确的,root 是指定目录的上级目录,并且该上级目录要含有 location 指定名称的同名目录。另外,根据前文所述,使用 alias 标签的目录块中不能使用 rewrite 的 break。 alias 虚拟目录配置中,location 匹配的 path 目录如果后面不带"/“,那么访问的 url 地址中这个 path 目录后面加不加”/“不影响访问,访问时它会自动加上”/“; 但是如果 location 匹配的 path 目录后面加上”/“,那么访问的 url 地址中这个 path 目录必须要加上”/“,访问时它不会自动加上”/“。如果不加上”/“,访问就会失败! root 目录配置中,location 匹配的 path 目录后面带不带”/",都不会影响访问。 在 nginx 配置中的良好习惯是: 在 location /中配置 root 目录; 在 location /path 中配置 alias 虚拟目录。 #直观理解如下形式: location /dev/{ alias /web/dev/doc/; #这个查找文件的路径直接是/web/dev/doc/ } location /dev/{ root /web/dev/doc/; #这个查找文件的路径应该是/web/dev/doc/dev } # 这里使用root配置 如果访问 192.168.2.3/pak/a.html 则对应的路径为:/usr/local/pak/a.html # 通过root配置则location配置的/pak/一定是要在root对应的/usr/local/目录下要有的目录 1 2 3 4 5 6 7 8 9 10 8.proxy_pass 结论: 如果 proxy_pass 末尾有斜杠/,proxy_pass 不拼接 location 的路径 如果 proxy_pass 末尾无斜杠/,proxy_pass 会拼接 location 的路径 1.proxy_pass 末尾有斜杠 location /api/ { proxy_pass http://127.0.0.1:8000/; } 1 2 3 请求地址:http://localhost/api/test 转发地址:http://127.0.0.1:8000/test 2.proxy_pass 末尾无斜杠 location /api/ { proxy_pass http://127.0.0.1:8000; } 1 2 3 请求地址:http://localhost/api/test 转发地址:http://127.0.0.1:8000/api/test 3.proxy_pass 包含路径,且末尾有斜杠 location /api/ { proxy_pass http://127.0.0.1:8000/user/; } 1 2 3 请求地址:http://localhost/api/test 转发地址:http://127.0.0.1:8000/user/test 4.proxy_pass 包含路径,末尾无斜杠 location /api/ { proxy_pass http://127.0.0.1:8000/user; } 1 2 3 请求地址:http://localhost/api/test 转发地址:http://127.0.0.1:8000/usertest 9.限流功能 nginx 提供了两种限流方式, 一种是限制请求速率 一种是限制连接数量 限制请求速率:nginx 的 ngx_http_limit_req_module 模块提供限制请求处理速率的能力,使用了漏桶算法(leaky bucket algorithm)。我们可以想像有一只上面进水、下面匀速出水的桶,如果桶里面有水,那刚进去的水就要存在桶里等下面的水流完之后才会流出,如果进水的速度大于水流出的速度,桶里的水就会满,这时水就不会进到桶里,而是直接从桶的上面溢出。对应到处理网络请求,水代表从客户端来的请求,而桶代表一个队列,请求在该队列中依据先进先出(FIFO)算法等待被处理。漏的水代表请求离开缓冲区并被服务器处理,溢出代表了请求被丢弃并且永不被服务。 漏桶算法 limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; server { location ~* \.(html)$ { limit_req zone=mylimit; } } 1 2 3 4 5 6 7 limit_req_zone 用于设置限流和共享内存区域的参数,格式为:limit_req_zone key zone rate。 key:定义限流对象,$binaryremote_addr 是 nginx 中的变量,表示基于 remote_addr(客户端 IP) 来做限流,binary 是二进制存储。使用 $binary_remote_addr 而不是 $remote_addr 是因为二进制存储可以压缩内存占用量。 $remote_addr 变量的大小从 7 到 15 个字节不等,而 $binary_remote_addr 变量的大小对于 IPv4 始终为 4 个字节,对于 IPv6 地址则为 16 个字节。 zone:定义共享内存区来存储访问信息,访问信息包括每个 IP 地址状态和访问受限请求 URL 的频率等。zone 的定义又分为两个部分:由 zone= 关键字标识的区域名称,以及冒号后面的区域大小。myLimit:10m 表示一个大小为 10M,名字为 myLimit 的内存区域。1M 能存储 16000 个 IP 地址的访问信息,myLimit 大概可以存储约 160000 个地址。nginx 创建新记录的时候,会移除前 60 秒内没有被使用的记录,如果释放的空间还是存储不了新的记录,会返回 503 的状态码。 rate:设置最大的访问速率。rate=2r/s(为了好模拟,rate 设置的值比较小),表示每秒最多处理 2 个请求。事实上 nginx 是以毫秒为粒度追踪请求的,rate=2r/s 实际上是每 500 毫秒 1 个请求,也就是说,上一个请求完成后,如果 500 毫秒内还有请求到达,这些请求会被拒绝(默认返回 503,如果想修改返回值,可以设置 limit_req_status)。 limit_req_zone 只是设置限流参数,如果要生效的话,必须和 limit_req 配合使用。limit_req 的格式为:limit_req zone=name [burst=number] [nodelay]。 上面的例子只简单指定了 zone=mylimit,表示使用 mylimit 这个区域的配置,在请求 html 文件时进行限流。我们可以理解为这个桶目前没有任何储存水滴的能力,到达的所有不能立即漏出的请求都会被拒绝。如果我 1 秒内发送了 10 次请求,其中前 500 毫秒 1 次,后 500 毫秒 9 次,那么只有前 500 毫秒的请求和后 500 毫秒的第一次请求会响应,其余请求都会被拒绝。 limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; server { location ~* \.(html)$ { limit_req zone=mylimit burst=5; } } 1 2 3 4 5 6 7 burst 表示在超过设定的访问速率后能额外处理的请求数。当 rate=2r/s 时,表示每 500ms 可以处理一个请求。burst=5 时,如果同时有 10 个请求到达,nginx 会处理第 1 个请求,剩余 9 个请求中,会有 5 个被放入队列,剩余的 4 个请求会直接被拒绝。然后每隔 500ms 从队列中获取一个请求进行处理,此时如果后面继续有请求进来,如果队列中的请求数目超过了 5,会被拒绝,不足 5 的时候会添加到队列中进行等待。我们可以理解为现在的桶可以存 5 滴水: limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; server { location ~* \.(html)$ { limit_req zone=mylimit burst=5 nodelay; } } 1 2 3 4 5 6 7 nodelay 表示不延迟。设置 nodelay 后,第一个到达的请求和队列中的请求会立即进行处理,不会出现等待的请求。需要注意的是,虽然队列中的 5 个请求立即被处理了,但是队列中的位置依旧是按照 500ms 的速度依次被释放的。后面的 4 个请求依旧是被拒绝的,长期来看并不会提高吞吐量的上限,长期吞吐量的上限是由设置的 rate 决定的。 nginx 限流使用了令牌桶算法: 漏桶算法和令牌桶算法都是用于实现流量控制和限流的算法,但它们的原理和适用场景略有不同。 漏桶算法: 漏桶算法模拟了一个漏桶,请求被认为是水滴,以固定的速率流出(漏出)系统。如果流入的请求速率超过了漏桶的容量,多余的请求将会被丢弃或者等待下一个时间段。漏桶算法适用于平滑流量,防止系统被大量突发流量压垮。但是,对于短时间内的突发流量,漏桶算法并不是特别有效,因为它无法快速处理瞬时大量的请求,而只能以固定的速率处理。 令牌桶算法: 令牌桶算法也是一种流量控制算法,它基于一个令牌桶的概念。令牌以一定的速率被添加到桶中,每个请求在处理之前需要获取一个令牌,如果没有可用的令牌,则请求将被暂时阻塞或丢弃。令牌桶算法可以适应瞬时的突发流量,因为当桶中积累足够多的令牌时,可以快速处理突发请求,而不会受限于固定的速率。这使得令牌桶算法更适合处理突发流量的情况。 所以,总的来说,漏桶算法更适合平滑流量,而令牌桶算法更适合应对突发流量。在实际应用中,可以根据需求选择合适的算法来实现流量控制和限流。 五.docker 安装 nginx 1.安装步骤 #查找nginx docker search nginx #下载镜像 docker pull nginx:latest #查看本地镜像 docker images #运行容器 docker run --name nginx-test -p 8080:80 -d nginx 参数说明: --name nginx-test:容器名称。 -p 8080:80: 端口进行映射,将本地 8080 端口映射到容器内部的 80 端口。 -d nginx: 设置容器在在后台一直运行。 #访问是否成功 127.0.01:8080 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 2.启动命令 #启动nginx,并挂在配置文件目录到宿主机 docker run -d --name deepexi-belle-damo-nginx \ --privileged=true \ --dns 114.114.114.114 \ -p 80:80 \ -v /etc/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf \ --restart=always deploy.deepexi.com/datasense-test/deepexi-belle-damo-nginx:v1.0.0 1 2 3 4 5 6 7 六.配置 https 1.上传证书 scp /Users/qinyingjie/Downloads/www.qinyingjie.top_nginx/www.qinyingjie.top_bundle.crt root@43.139.90.182:/etc/nginx scp /Users/qinyingjie/Downloads/www.qinyingjie.top_nginx/www.qinyingjie.top.key root@43.139.90.182:/etc/nginx 1 2 3 2.http 的配置 # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { listen 80; server_name qinyingjie.top; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { root html; index index.html index.htm; proxy_pass http://127.0.0.1:8080/; } location ~ .*\.(gif|jpg|jpeg|png|jfif|webp)$ { root /kwan/; autoindex on ; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } # Settings for a TLS enabled server. # # server { # listen 443 ssl http2 default_server; # listen [::]:443 ssl http2 default_server; # server_name _; # root /usr/share/nginx/html; # # ssl_certificate "/etc/pki/nginx/server.crt"; # ssl_certificate_key "/etc/pki/nginx/private/server.key"; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 10m; # ssl_ciphers PROFILE=SYSTEM; # ssl_prefer_server_ciphers on; # # # Load configuration files for the default server block. # include /etc/nginx/default.d/*.conf; # # location / { # } # # error_page 404 /404.html; # location = /40x.html { # } # # error_page 500 502 503 504 /50x.html; # location = /50x.html { # } # } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 3.证书文件名称 www.qinyingjie.top_bundle.crt www.qinyingjie.top.key 1 2 4.https 的配置 # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { listen 80; #请填写绑定证书的域名 server_name www.qinyingjie.top; #把http的域名请求转成https return 301 https://$host$request_uri; } server { #SSL 默认访问端口号为 443 listen 443 ssl; #请填写绑定证书的域名 server_name www.qinyingjie.top; #请填写证书文件的相对路径或绝对路径 ssl_certificate www.qinyingjie.top_bundle.crt; #请填写私钥文件的相对路径或绝对路径 ssl_certificate_key www.qinyingjie.top.key; ssl_session_timeout 5m; #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #请按照以下协议配置 ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; location / { #网站主页路径。此路径仅供参考,具体请您按照实际目录操作。 #例如,您的网站主页在 Nginx 服务器的 /etc/www 目录下,则请修改 root 后面的 html 为 /etc/www。 root html; index index.html index.htm; proxy_pass http://127.0.0.1:8080/; } location ~ .*\.(gif|jpg|jpeg|png|jfif|webp)$ { root /kwan/; autoindex on ; } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 5.验证 #检查配置是否正确(常用) nginx -t 1 2 6.加载配置 nginx -s reload 1 7.查看日志 #全局查看 cat /var/log/nginx/error.log #尾部查看 tail -f /var/log/nginx/error.log ———————————————— 版权声明:本文为CSDN博主「檀越剑指大厂」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qyj19920704/article/details/134259159
-
📕弊端 3条SQL语句都是删除操作,但是经过语法解析,优化,编译会生成3条不同的SQL语句,降低性能也浪费空间。 delete from emp where id = 1; delete from emp where id = 2; delete from emp where id = 3; //优化后执行3条不同的SQL语句 📕预编译SQL的优势 使用参数占位符#{}替代 预编译生成的SQL语句相同,故第二次、第三次,省去了解析和优化过程,提高性能 delete from emp where id = #{id}; -- 预编译后的SQL语句 delete from emp where id = ?; 预编译可防止SQL注入 下面是一个登户登录的校验,当你输入用户名和密码,点击登录,信息传到服务器,服务器端会从User表中查询有无该用户,以下是两种SQL语句的差别。 -- 用户登录校验 select username, password from user where username='张三' and password='123' -- 普通语句 select username, password from user where username='saggd' and password='' or '1'='1'; -- 预编译SQL安全 select username, password from user where username=? ans password=?; 小结: 普通语句编译后会将参数以字符串的形式拼接到SQL语句中,这就造成了语句的恒成立 预编译SQL编译后将参数整体视为一个字符串,当语句开始执行时,才进行替换 📕两种参数占位符 #{} 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值。 使用时机:参数传递,都使用#{…} ${} 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题。 使用时机:如果对表名、列表进行动态设置时使用。 📕小结 预编译SQL利用参数占位符编译生成的SQL语句相同,性能高效 可防止SQL注入 二、动态SQL 📕概念介绍: 随着用户的输入或外部条件的变化而变化的SQL语句,我们称为 动态SQL。 📕案例: 📕动态SQL语句: <if>用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。 用法:test属性为if的判断条件 实现:例如动态sql实现条件查询 <!-- 动态sql - if--> <select id="select" resultType="com.itpan.pojo.Emp"> select * from emp <where> <if test="name != null"> name like concat('%', #{name}, '%') </if> <if test="gender != null"> and gender = #{gender} </if> <if test="begin != null and end != null"> and entrydate between #{begin} and #{end} </if> </where> order by update_time desc </select> 注意: 如果name字段为空,sql语句为select * from emp where and gender = #{gemder}…… 引入<where></where>标签: where 元素只会在子元素有内容的情况下才插入where子句。而且会自动去除子句的开头的AND 或OR 同理update时也要引入<set></set>标签去除多余 , <foreach>遍历集合或数组给字段赋值 属性介绍 : collection:集合或数组名 item:要分割的字段名 separator:每次遍历的分隔符 open:遍历开始前拼接的片段 close:遍历开始后拼接的片段 实现:例如实现批量删除 <!-- 批量删除元素--> <!-- ids是List<Integer>集合> <delete id="deleteById"> delete from emp where id in <foreach collection="ids" item="id" separator="," open="(" close=")"> #{id} </foreach> </delete> <sql>与<include> <sql>:定义可重用的 SQL 片段。 <include>:通过属性refid,指定包含的sql片段。 📕应用场景总结: <if> 用于判断条件是否成立,如果条件为true,则拼接SQL。 形式:<if test="name != null">…</if> <where> where 元素只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND 或OR <set> 动态地在行首插入 SET 关键字,并会删掉额外的逗号。(用在update语句中) <foreach> 遍历集合或数组给字段赋值 形式<foreach collection=集合或数组名 item=字段名 separator="," open="(" close=")"> <sql><include> sql封装相同代码 include引入 三、总结: 🌈 动态SQL是重点,也是我们开发中最为常用的SQL语句 🌈 #{} 与 ${}占位符有什么区别 -> 大厂面试题 🌈 预编译SQL的优势 ———————————————— 版权声明:本文为CSDN博主「不会就选C.」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/Panci_/article/details/134131428
-
方法一:通过mysql控制台直接设置密码 第一步 我们打开mysql console,输入mysql原先密码,按回车键进去,这里原密码为空,如下图所示: 第二步 输入“set password =password('123456');”,按回车键之后,就成功将密码改为123456了,如果想修改密码为其他,直接将123456改成想要设置的密码就可以,如下图所示: 第三步 我们使用mysql图形界面工具navicat尝试一下密码是否修改成功,新建连接,输入数据库用户名和刚刚设置的密码,点击确定,如下图所示: 第四步 我们双击建立的连接,可以看到已经成功建立连接,进去了mysql数据库,代表密码修改成功了,如下图所示: 方法二:通过修改mysql中user表修改密码 第一步 打开mysql控制台,输入原密码进去之后,输入“use mysql;”,按回车键进去mysql数据库中,如下图所示: 第二步 输入“update user set password=password('123456') where user='root';”,按回车键,将原密码修改为123456,如下图所示: ———————————————— 版权声明:本文为CSDN博主「红烧小肥杨」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_42874480/article/details/133142329
-
查询当前所有的表SQL> select * from tab;SQL> select * from cat where table_type=’TABLE’;//可能会有viewSQL>select * from user_tables;mysql> show tables;c:/mysql/bin>mysqlshow 库名显示当前连接用户(库)SQL> show usermysql> connect查看帮助SQL> ?mysql> help显示表结构SQL> desc 表名SQL> describe 表名mysql> desc 表名;mysql> describe 表名;mysql> show columns from 表名;c:/mysql/bin>mysqlshow 库名 表名日期函数SQL> select sysdate from dual;mysql> select now();mysql> select sysdate();mysql> select curdate();mysql> select current_date;mysql> select curtime();mysql> select current_time;日期格式化SQL> select to_char(sysdate,'yyyy-mm-dd') from dual;SQL> select to_char(sysdate,'hh24-mi-ss') from dual;mysql> select date_format(now(),'%Y-%m-%d');mysql> select time_format(now(),'%H-%i-%S');日期函数(增加一个月)SQL> select to_char(add_months(to_date('20000101','yyyymmdd'),1),'yyyy-mm-dd') from dual;结果:2000-02-01SQL> select to_char(add_months(to_date('20000101','yyyymmdd'),5),'yyyy-mm-dd') from dual;结果:2000-06-01mysql> select date_add('2000-01-01',interval 1 month);结果:2000-02-01mysql> select date_add('2000-01-01',interval 5 month);结果:2000-06-01别名SQL> select 1 a from dual;SQL>select 1 as a from dual; //as可以省略mysql> select 1 as a;字符串截取函数SQL> select substr('abcdefg',1,5) from dual;SQL> select substr('abcdefg',1,5) from dual;结果:abcdemysql> select substring('abcdefg',2,3);结果:bcdmysql> select mid('abcdefg',2,3);结果:bcdmysql> select substring('abcdefg',2);结果:bcdefgmysql> select substring('abcdefg' from 2);结果:bcdefg另有SUBSTRING_INDEX(str,delim,count)函数返回从字符串str的第count个出现的分隔符delim之后的子串。如果count是正数,返回最后的分隔符到左边(从左边数) 的所有字符。如果count是负数,返回最后的分隔符到右边的所有字符(从右边数)。执行外部脚本命令SQL >@a.sql1:mysql> source a.sql2:c:/mysql/bin>mysql <a.sql3:c:/mysql/bin>mysql 库名 <a.sql导入、导出工具exp.exeexp73.exeimp.exeimp73.exemysqldump.exemysqlimport.exe改表名SQL> rename a to b;mysql> alter table a rename b;执行命令;<回车>/rrun;<回车>goegodistinct用法SQL> select distinct 列1 from 表1;SQL> select distinct 列1,列2 from 表1;mysql> select distinct 列1 from 表1;mysql> select distinct 列1,列2 from 表1;注释--/*与*/#--/*与*/当作计算器SQL> select 1+1 from dual;mysql> select 1+1;限制返回记录条数SQL> select * from 表名 where rownum<5;mysql> select * from 表名 limit 5;新建用户(库)SQL> create user 用户名 identified by 密码;mysql> create database 库名;删用户(库)SQL> drop user 用户名;mysql> drop database 库名;查询索引SQL> select index_name,table_name from user_indexes;mysql> show index from 表名 [FROM 库名];通配符“%”和“_”“%”和“_”SQL语法SELECT selection_list 选择哪些列FROM table_list 从何处选择行WHERE primary_constraint 行必须满足什么条件GROUP BY grouping_columns 怎样对结果分组HAVING secondary_constraint 行必须满足的第二条件ORDER BY sorting_columns 怎样对结果排序SELECT selection_list 选择哪些列FROM table_list 从何处选择行WHERE primary_constraint 行必须满足什么条件GROUP BY grouping_columns 怎样对结果分组HAVING secondary_constraint 行必须满足的第二条件ORDER BY sorting_columns 怎样对结果排序LIMIT count 结果限定自动增长的数据类型处理create sequence myseq increment by 1 start with 1 maxvalue 99999; 主键列上加auto_increment
-
大家好,本月给大家带来的是CodeArts,lot物联网,数据库等多个模块的问题求助,以及干货合集,希望可以帮到大家。 问题求助: 1.如何在CodeArts中进行版本控制和团队协作? https://bbs.huaweicloud.com/forum/thread-02109134113938083048-1-1.html 2.如何在CodeArts中进行代码重构和优化? https://bbs.huaweicloud.com/forum/thread-02116134113913776048-1-1.html 3.如何在CodeArts中实现代码的自动化测试和验证? https://bbs.huaweicloud.com/forum/thread-0296134113886594043-1-1.html 4.如何在CodeArts中进行代码审查和质量控制? https://bbs.huaweicloud.com/forum/thread-02109134113860762047-1-1.html 5.在CodeArts中如何使用代码模板进行快速开发? https://bbs.huaweicloud.com/forum/thread-0248134113772174042-1-1.html 6.使用标准系统内核的Openharmony的开发板如何接入华为云IoT https://bbs.huaweicloud.com/forum/thread-02125132312741820009-1-1.html 7.华为云IOT后续能实现接收上传的视频或者图片数据吗? https://bbs.huaweicloud.com/forum/thread-0231132224565537004-1-1.html 8.华为云的IOT有没有一体化的应用程序开发框架? https://bbs.huaweicloud.com/forum/thread-0291132224385357002-1-1.html 9.问下论坛大佬们,人脸的侧脸识别不是很精确如何解决? https://bbs.huaweicloud.com/forum/thread-02124132223415290004-1-1.html 10.如何有效地利用ModelArts进行模型训练和调优? https://bbs.huaweicloud.com/forum/thread-02125134010854460033-1-1.html 11.新手教程怎么都这么难,这是什么原因啊大佬们!! https://bbs.huaweicloud.com/forum/thread-02115133605091189031-1-1.html 12.关于AI Gallery平台成长值兑换平台专项算力资源的活动什么时候上线啊? https://bbs.huaweicloud.com/forum/thread-0275133102137993004-1-1.html 13.ModelArts创建notebook进入终端训练模型产生的文件如何导出? https://bbs.huaweicloud.com/forum/thread-0236132906603549009-1-1.html 14.CPU:2核心8GB 使用conda创建虚拟Python环境会有很大的几率失败,报错如下:(大于此规格目前正常) https://bbs.huaweicloud.com/forum/thread-0235132113651876033-1-1.html 15.modelbox部署 在rk3588s上,运行hello_world demo 报错debain os need load libgomp https://bbs.huaweicloud.com/forum/thread-0249131878466628023-1-1.html 技术干货 1.一文详解MYSQL的多版本并发控制MVCC(Multi-Version Concurrency Control)【转】 https://bbs.huaweicloud.com/forum/thread-02109134115448959053-1-1.html 2.mysql中删除数据的四种方法小结【转】 https://bbs.huaweicloud.com/forum/thread-02109134115399646052-1-1.html 3.Mysql实现递归树查询的使用示例【转】 https://bbs.huaweicloud.com/forum/thread-0257134115101586049-1-1.html 4.MySQL 格式化时间的实现示例【转】 https://bbs.huaweicloud.com/forum/thread-02116134115040577051-1-1.html 5.有效查询MySQL表中重复数据的方法和技巧分享【转】 https://bbs.huaweicloud.com/forum/thread-02116134114971706050-1-1.html 6.Python3第三方模块之Pillow模块的使用详解【转】 https://bbs.huaweicloud.com/forum/thread-0273134098427488045-1-1.html 7.使用python连接Linux服务器发送指定命令的示例代码【转】 https://bbs.huaweicloud.com/forum/thread-0248134098310854040-1-1.html 8.python curl2pyreqs 生成接口脚本实战教程【转】 https://bbs.huaweicloud.com/forum/thread-02125134098161489039-1-1.html 9.python通过socket搭建极简web服务器的实现代码【转】 https://bbs.huaweicloud.com/forum/thread-0296134098104530042-1-1.html 10.Windows系统使用bat批量修改文件名的使用示例【转】 https://bbs.huaweicloud.com/forum/thread-0273134098018508044-1-1.html 11.DOS下常用的20个基本操作命令【转】 https://bbs.huaweicloud.com/forum/thread-0248134097935982039-1-1.html 12.Boston数据集预测放假及应用优缺点评估【转】 https://bbs.huaweicloud.com/forum/thread-02116134097856413045-1-1.html 13.python + winrm 实现远程连接Windows服务器并执行指定命令的操作过程【转】 https://bbs.huaweicloud.com/forum/thread-02116134097701112044-1-1.html 14.pandas探索你的数据实现可视化示例详解【转】 https://bbs.huaweicloud.com/forum/thread-02116134097466266043-1-1.html 15.Python pydotplus安装及可视化图形创建教程【转】 https://bbs.huaweicloud.com/forum/thread-02109134097344935046-1-1.html
-
1、概述MVCC是一种用于数据库管理系统的并发控制技术,允许多个事务同时访问数据库,而不会导致读写冲突。也就是说在读写的时候,线程不用去争抢读写锁。因为加锁的过程比较耗性能。当然很多时候还是必须的,不能避免,比如说,去ATM机取钱的时候,同时又在手机APP上进行提现,这种操作就需要加锁,不能让其同时提现,一次只能一个操作,而且只有在ATM取钱这个事务被提交之后才能做其他操作。处理并发的场景无外乎三种:读、读:这个不需要做控制,因为数据没有变化读、写:存在线程安全问题,可能出现脏读、幻读,不可重复读写、写:存在线程安全问题,可能出现更新丢失的情况这里介绍的MVCC是在存储引擎为InnoDB实现的,目的也是为了提高数据库的并发性能,不使用加锁的方式去处理读、写并发。2、MVCC特点这里的读操作,有两种方式:快照读:SELECT语句,在读写的时候不用加锁,所以效率很高,但也存在读取的时候有更新操作,可能会读到历史数据。当前读:读取的是最新数据,是一种悲观锁的操作。它会对当前读取的数据进行加锁,避免其他事物对其进行写操作。主要包括以下几种操作:select lock in share mode(共享锁)select for update(排他锁)update(排他锁)insert(排他锁)delete(排他锁)3、准备数据在介绍之前,没有安装MYSQL的,可以先进行安装,下载地址在线搜索安装好了之后,我们就新建库与表,插入一些数据来做个测试CREATE DATABASE mydb; USE mydb; CREATE TABLE `tb1` ( `id` int(12) NOT NULL AUTO_INCREMENT, `name` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8; INSERT INTO tb1(name) VALUES ('XIAO1'),('XIAO2'),('XIAO3'); CREATE TABLE `tb2` ( `id` int(12) NOT NULL AUTO_INCREMENT, `name` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=myisam; INSERT INTO tb2(name) VALUES ('LAO1'),('LAO2'),('LAO3');这里我特地创建了两张表,分别是表tb1对应的是InnoDB引擎,表tb2对应的是myisam引擎,创建之后,也可以看到两者的数据格式也是不一样的,我们先查询下,新建的数据库mydb以及保存的数据在什么地方:mysql> show variables like '%datadir%'; +---------------+---------------------------------------------+ | Variable_name | Value | +---------------+---------------------------------------------+ | datadir | C:\ProgramData\MySQL\MySQL Server 8.0\Data\ | +---------------+---------------------------------------------+ 1 row in set, 1 warning (0.00 sec)然后可以看到,InnoDB引擎对应的是:tb1.ibd ,myisam对应的是:tb2.MYD(数据)、tb2.MYI(索引)、tb2_402.sdi(表结构)[这个在以前的版本没有出现]在MySQL5.5之后都是默认为InnoDB引擎4、MVCC原理在MYSQL存储的数据中,除了我们显式定义的字段,还隐含着两个字段。trx_id:事务id,每进行一次事务操作,就会自增1。roll_pointer:回滚指针,用于找到上一个版本的数据,结合undolog进行回滚。我们用SELECT读数据时,这一时刻的数据会有很多个版本【比如上图四个版本】,但我们并不知道读取哪个版本,依赖ReadView来对我们进行版本的选择,通过ReadView我们就能够知道读取哪个版本。我们来看下这个ReadView的定义class ReadView { /* ... */ private: trx_id_t m_low_limit_id; /* 大于等于这个 ID 的事务均不可见 */ trx_id_t m_up_limit_id; /* 小于这个 ID 的事务均可见 */ trx_id_t m_creator_trx_id; /* 创建该 Read View 的事务ID */ trx_id_t m_low_limit_no; /* 事务 Number, 小于该 Number 的 Undo Logs 均可以被 Purge */ ids_t m_ids; /* 创建 Read View 时的活跃事务列表 */ m_closed; /* 标记 Read View 是否 close */ }字段的解释:m_low_limit_id:目前出现的最大事务ID+1(下一个将被分配的事务ID)。大于等于这个ID的数据版本均不可见,也就访问不到。m_up_limit_id:活跃事务列表m_ids中最小的事务ID,如果为空,则m_up_limit_id为m_low_limit_id。小于这个ID的数据版本均可见。m_ids:ReadView创建时其他未提交的活跃事务ID列表。创建ReadView时,将当前未提交事务ID记录下来,后续即使它们修改了记录行的值,对于当前事务也是不可见的。m_ids 不包括当前事务自己和已提交的事务(正在内存中)m_creator_trx_id:创建该ReadView的事务ID5、实践操作开四个终端,新建三个事务,两个写操作,一个读操作,还有一个就是单纯的查询。大家可以根据不同的进入时间来了解这个过程,会产生未提交和已提交事务状态,对应的查询信息都是不一样的,具体代码分别如下:BEGIN; UPDATE tb1 SET name='XXX' WHERE id=1; UPDATE tb1 SET name='YYY' WHERE id=1; COMMIT; BEGIN; UPDATE tb1 SET name='ZZZ' WHERE id=1; UPDATE tb1 SET name='QQQ' WHERE id=1; DELETE FROM tb1 WHERE id=5; COMMIT; BEGIN; SELECT * FROM tb1 WHERE id=1; COMMIT; SELECT * FROM tb1;6、小结对于这种读写并发,以及对性能的要求,大家需要看实际业务情况来做决定,其中这里主要是介绍InnoDB引擎,这个要高效很多,在以前的旧版本可能大家使用MyISAM这个更多,因为性能很好,不过不支持事务操作,所以很多场景也就不适应,MYSQL5.5版本之后就是默认InnoDB引擎了。最后大家也可以尝试在表tb2中去尝试下,看下是什么结果,因为这张表使用的是MyISAM引擎,就起不到作用了。另外需要注意的是,事务的提交是默认自动的,有些时候需要关闭,将默认的1修改为0:SET AUTOCOMMIT=0; SELECT @@AUTOCOMMIT;比如说对于脏读的情况,我们需要当前读,也就是需要排它锁:SET AUTOCOMMIT=0; BEIGIN; DELETE FROM tb1 WHERE id=2;
-
写在前面 在MySQL数据库中,删除数据是一个常见的操作,它允许从表中移除不再需要的数据。在执行删除操作时,需要谨慎,以免误删重要数据。方法介绍以下是MySQL中删除数据的几种方法:DELETE语句DROP TABLE语句TRUNCATE TABLE使用外键约束1. DELETE语句DELETE语句是最常用的删除数据方法之一。它允许您根据特定的条件从表中删除数据。下面是DELETE语句的基本语法:1DELETE FROM table_name WHERE condition;table_name 是要删除数据的表名。condition 是一个可选的条件,用于指定要删除的行。如果不提供条件,将删除表中的所有数据。示例: 假设有一个名为students的表,您可以使用以下DELETE语句删除年龄小于18岁的学生记录:1DELETE FROM students WHERE age < 18;2. DROP TABLE语句:DROP TABLE语句用于删除整个表,包括表的结构和数据。这是一个危险的操作,需要慎重使用,因为一旦执行,数据将无法恢复。1DROP TABLE table_name;示例:如果要完全删除名为products的表及其所有数据,您可以使用以下DROP TABLE语句:1DROP TABLE products;3. TRUNCATE TABLETRUNCATE TABLE是MySQL中用于快速删除表中所有数据的操作。与DELETE语句不同,TRUNCATE TABLE操作不仅删除表中的数据,还将表的结构保留在原样。这意味着表的列、索引、主键等定义都不会受到影响,只是数据被清空。下面是TRUNCATE TABLE操作的详细介绍:语法:1TRUNCATE TABLE table_name;table_name 是要执行TRUNCATE操作的目标表的名称。特点和注意事项:速度快: TRUNCATE TABLE通常比使用DELETE语句删除所有数据要快得多。这是因为TRUNCATE不会逐行删除数据,而是直接从表中删除数据页,因此效率更高。无法使用WHERE子句: TRUNCATE TABLE不允许使用WHERE子句来指定特定的删除条件。它总是删除整个表中的所有数据。如果需要按条件删除数据,应该使用DELETE语句。不记录删除操作: TRUNCATE TABLE操作通常不生成事务日志,因此不会记录删除操作。这可以节省磁盘空间和提高性能。但是,这也意味着无法通过回滚来恢复被删除的数据。如果需要记录删除操作并能够进行回滚,应该使用DELETE语句,并在事务中执行。自动重置AUTO_INCREMENT计数器: 当使用TRUNCATE TABLE删除数据时,与表关联的AUTO_INCREMENT计数器将自动重置为1。这意味着下次插入新数据时,将从1开始计数。需要适当权限: 执行TRUNCATE TABLE操作需要足够的权限。通常,只有具有表的DELETE权限的用户才能执行TRUNCATE TABLE操作。示例:假设有一个名为employees的表,您可以使用TRUNCATE TABLE操作来清空该表中的所有员工数据,但保留表的结构:1TRUNCATE TABLE employees;这将快速清空employees表,但表的结构、索引和其他定义将保持不变,可以立即重新插入新的数据。总之,TRUNCATE TABLE是一个用于快速删除表中所有数据的有用工具,特别是在需要清空表而不影响表结构时。然而,由于其不支持条件删除和不记录操作日志,应该根据特定的需求来选择是使用TRUNCATE TABLE还是DELETE语句来执行删除操作。4. 使用外键约束:如果表之间存在外键关系,可以使用外键约束来删除数据。外键约束可以确保删除操作不会破坏引用完整性。删除操作将自动级联到相关表中的数据。示例: 假设有两个表orders和order_items,order_items表具有指向orders表的外键。可以使用DELETE语句删除orders表中的订单,外键约束将自动删除order_items表中相应的订单项。1DELETE FROM orders WHERE order_id = 123;方法优缺点以下是前面提到的MySQL中删除数据的几种方法的优缺点的总结:1. DELETE语句:优点:允许根据条件删除数据,具有灵活性。可以记录删除操作,支持事务。不会重置AUTO_INCREMENT计数器,保留表结构。缺点:删除大量数据时较慢,因为它逐行删除。会生成事务日志,可能会增加数据库的负担。2. TRUNCATE TABLE语句:优点:非常快速,特别适用于大型表的数据清空。不生成事务日志,减少数据库负担。保留表结构,不会重置AUTO_INCREMENT计数器。缺点:无法指定条件删除,总是删除整个表中的数据。不记录删除操作,无法回滚。需要适当权限。3. DROP TABLE语句:优点:快速删除整个表及其数据。不会生成事务日志,减少数据库负担。缺点:完全删除表,包括表结构和数据,无法恢复。需要谨慎使用,容易导致数据丢失。4. 使用外键约束:优点:用于维护数据完整性,确保删除操作不会破坏引用关系。自动级联删除相关数据。缺点:需要在表设计中定义外键关系。无法用于快速清空整个表或删除大量数据。总结 这些是MySQL中删除数据的主要方法。在执行删除操作时,请确保备份重要数据,以免意外删除。此外,根据您的需求选择适当的删除方法,以确保数据库的完整性和性能。如果不确定如何执行删除操作,建议在测试环境中进行测试,以避免在生产环境中发生意外。
-
大家好! 在我们日常工作中,经常会遇到一些问题,它们的一些解决方案通常会用到递归这一强大的技术手段。递归不仅能帮助我们更高效的解决问题,还可以使代码更简介、更易于理解, 今天我来给大家分享如何在实际工作中使用mysql8+实现递归在大型组织中,理解员工建的层级关系至关重要。无论是管理、报告和策划,一个清晰的组织层级视图都是必不可少的。但是如何有效地从一个大型、复杂的员工数据库中提取到这样的层级信息呢?递归执行分析mysql8+递归查询的实现是基于 WITH RECURSIVE语句。它从一个初始的"基础情况"开始,然后不断的重复或"递归" 的一个连接操作,直到满足某个条件为止。以下是递归查询的基本结构:1. 基础情况: 这是递归的起点,也就是根节点,在我们场景中根节点是CEO或者它的上级为null。2. 递归情况: 基于基础情况,查询将继续扩展,包括下一级的员工,然后类推。WITH RECURSIVE hierarchy AS ( -- 基础情况 ... UNION ALL -- 递归情况 ... ) select xxx from hierarchydemo数据模拟插入10w条数据, 层级最高6层DROP TABLE IF EXISTS employees; CREATE TABLE employees ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100), manager_id INT, FOREIGN KEY (manager_id) REFERENCES employees(id) ); -- 新增根节点数据 INSERT INTO employees (name) VALUES ('CEO'); -- 创建执行过程 DELIMITER $$ CREATE PROCEDURE InsertLargeAmountOfData() BEGIN DECLARE id INT DEFAULT 2; DECLARE parentId INT DEFAULT 1; DECLARE counter INT DEFAULT 0; -- 第2层 WHILE counter < 10 DO INSERT INTO employees (name, manager_id) VALUES (CONCAT('L2-', id), 1); SET id = id + 1; SET counter = counter + 1; END WHILE; SET counter = 0; -- 第3层 WHILE counter < 100 DO SET parentId = 1 + FLOOR(counter / 10) + 1; INSERT INTO employees (name, manager_id) VALUES (CONCAT('L3-', id), parentId); SET id = id + 1; SET counter = counter + 1; END WHILE; SET counter = 0; -- 第4层 WHILE counter < 1000 DO SET parentId = 11 + FLOOR(counter / 100); INSERT INTO employees (name, manager_id) VALUES (CONCAT('L4-', id), parentId); SET id = id + 1; SET counter = counter + 1; END WHILE; SET counter = 0; -- 第5层 WHILE counter < 10000 DO SET parentId = 111 + FLOOR(counter / 1000); INSERT INTO employees (name, manager_id) VALUES (CONCAT('L5-', id), parentId); SET id = id + 1; SET counter = counter + 1; END WHILE; SET counter = 0; -- 第6层 WHILE counter < 88889 DO SET parentId = 1111 + FLOOR(counter / 10000); INSERT INTO employees (name, manager_id) VALUES (CONCAT('L6-', id), parentId); SET id = id + 1; SET counter = counter + 1; END WHILE; END$$ DELIMITER ; -- 执行执行过程 CALL InsertLargeAmountOfData();查询demo数据WITH RECURSIVE hierarchy AS ( -- 基础情况 select id,name,manager_id from employees where manager_id is null UNION ALL -- 递归情况 select e.* from employees as e inner join hierarchy as h on e.manager_id = h.id ) select id,name,manager_id from hierarchy结果在以上图例中,通过调整manager_id is null 可以配置要查询某条数据及该数据所有子数据的查询出来的内容。??Tip! 查询的结果将以列表形式展现。若业务代码中需要完整的树状结构,可以在每个节点中关联其上级节点。最后,通过取manager_id is null的记录下的子节点数据,即可得到完整的树状数据。扩展字段扩展在业务中常常会需要查询某条记录并返回该字段在组织层次中的位置,你可以参考以下代码:WITH RECURSIVE hierarchy AS ( -- 基础情况:从CEO开始 SELECT id, name, manager_id, CAST(name AS CHAR(255)) AS hierarchy_path FROM employees WHERE manager_id IS NULL UNION ALL -- 递归情况:为每个下级员工添加上级 SELECT e.id, e.name, e.manager_id, CONCAT(h.hierarchy_path, ' > ', e.name) FROM employees e JOIN hierarchy h ON e.manager_id = h.id ) SELECT id, name, manager_id, hierarchy_path FROM hierarchy -- 查询某条数据条件 WHERE name = 'L3-111' ORDER BY id;结果如下图:
-
MySQL是一个非常流行的关系型数据库管理系统,它提供了一种使用SQL语言来管理和操作数据库的方法。在MySQL中,时间格式化是一个常见的需求,但很多人可能并不了解如何正确格式化时间。在本文中,我们将介绍MySQL如何正确格式化时间。MySQL日期和时间类型MySQL中有许多日期和时间类型,包括日期类型、时间类型、日期时间类型、时间戳类型等等。常用的日期类型有DATE、YEAR、TIME;常用的日期时间类型有DATETIME和TIMESTAMP。具体的类型介绍可以参考MySQL官方文档。DATE格式化DATE类型的格式化是比较容易的,我们可以使用DATE_FORMAT函数将DATE类型的日期格式化为我们需要的格式。例如,我们将日期格式化为“YYYY-MM-DD”格式:1SELECT DATE_FORMAT('2022-03-24', '%Y-%m-%d');这将返回“2022-03-24”。其中,%Y表示年份,%m表示月份,%d表示日期。更多的格式化参数可以在MySQL官方文档中查看。TIME格式化TIME类型的格式化也很简单,我们可以使用TIME_FORMAT函数将TIME类型的时间格式化为我们需要的格式。例如,我们将时间格式化为“HH:MM:SS”格式:1SELECT TIME_FORMAT('21:36:28', '%H:%i:%s');这将返回“21:36:28”。其中,%H表示小时,%i表示分钟,%s表示秒钟。DATETIME格式化DATETIME类型的格式化和DATE类型的格式化类似,我们可以使用DATE_FORMAT函数将DATETIME类型的日期时间格式化为我们需要的格式。例如,我们将日期时间格式化为“YYYY-MM-DD HH:MM:SS”格式:1SELECT DATE_FORMAT('2022-03-24 21:36:28', '%Y-%m-%d %H:%i:%s');这将返回“2022-03-24 21:36:28”。TIMESTAMP格式化TIMESTAMP类型的格式化也和DATETIME类型的格式化类似,我们可以使用DATE_FORMAT函数将TIMESTAMP类型的时间戳格式化为我们需要的格式。例如,我们将时间戳格式化为“YYYY-MM-DD HH:MM:SS”格式:1SELECT DATE_FORMAT(FROM_UNIXTIME(1648157788), '%Y-%m-%d %H:%i:%s');这将返回“2022-03-24 21:36:28”。其中,FROM_UNIXTIME函数可以将Unix时间戳转换为日期时间格式。总结MySQL提供了多种日期和时间类型,在处理时间时需要根据不同类型选择不同的格式化方法。使用DATE_FORMAT函数可以很方便地将日期时间格式化为我们需要的格式。熟练掌握MySQL日期时间类型以及相关函数的使用方法,可以方便我们进行数据库的管理和操作。
-
方法一:使用COUNT()函数查询重复行COUNT()函数是MySQL中常用的聚合函数之一,它可以用于计算表中某个字段值的数量。利用这个函数,我们可以找到表中的重复值和它们的数量。以下是具体的步骤:编写SQL查询语句来选择你想要查找重复数据所在的数据表,同时选择你想要鉴定的字段。例如:SELECT field1, field2, COUNT(field2) FROM table_name GROUP BY field2 HAVING COUNT(field2)>1;以上语句将查询 table_name 表中 field2 字段的值,并找出出现次数大于1的记录。同时,该查询还会显示 field1 字段的值和该字段对应的 field2 记录中的重复次数。执行以上查询语句,你将会得到表中所有的重复数据以及对应的出现次数。你可以在查询结果中看到所有出现次数大于1的字段值,这意味着它出现了至少两次。方法二:使用DISTINCT关键字查询重复行DISTINCT 关键字可以帮助我们去除表中的重复数据。我们可以编写一条 SQL 查询语句来查找一列中的重复数据。以下是具体的步骤:编写SQL查询语句来选择你所需的表,同时选择需要查找的字段。例如:SELECT DISTINCT field1 FROM table_name WHERE field2=‘duplicate_value';以上语句将查询 table_name 表中所有的 field1 字段,并且只选择其中一个重复值。通过将查询结果与表中所有的唯一值进行比较,我们可以得到这个字段中的重复值。执行以上的查询语句,你将会得到表中所有的重复数据,同时还会得到所有唯一的 field1 字段值。方法三:使用自连接查询使用自连接查询是一种比较复杂的方法,但也是一种非常强大的方法,可以用于查找表中重复的行。以下是具体的步骤:编写SQL查询语句,将数据表自连接,使得查询结果中的数据表和原始表是同一个。我们需要选择所需的字段并指定必须相同的字段作为连接条件。例如,SELECT A. FROM table_name A INNER JOIN (SELECT field1, field2, COUNT() FROM table_name GROUP BY field1, field2 HAVING COUNT(*)>1) B ON A.field1=B.field1 AND A.field2=B.field2;以上语句将查询 table_name 表中两列数据:field1 和 field2。它们的值必须与表中的其他记录匹配,以帮助我们找出重复的行。在这个查询中,我们将表名设置为 A,将 inner join 自连接的副本称为 B。执行以上查询语句,你将会得到表中所有的重复数据。结论在MySQL中,查找表中重复的数据是一项常见的任务。本文介绍了三种常见的方法来查找表中的重复数据:使用 COUNT() 函数,使用 DISTINCT 关键字以及使用自连接查询。这些技巧都非常有效,你可以根据实际情况选择最合适的方法。无论哪种方法,都可以帮助你在数据库中有效地查找重复的数据。
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签