-
【摘要】 在当前GaussDB(DWS)的能力中主要支持两种过程化SQL语言,即基于PostgreSQL的PL/pgSQL以及基于Oracle的PL/SQL。本篇文章我们通过匿名块,函数,存储过程向大家介绍一下GaussDB(DWS)对于过程化SQL语言的基本能力。前言 GaussDB(DWS)中的PLSQL语言,是一种可载入的过程语言,其创建的函数可以被用在任何可以使用内建函数的地方。例如,可以创建复杂条件的计算函数并且后面用它们来定义操作符或把它们用于索引表达式。 SQL被大多数数据库用作查询语言。它是可移植的并且容易学习。但是每一个SQL语句必须由数据库服务器单独执行。 这意味着客户端应用必须发送每一个查询到数据库服务器、等待它被处理、接收并处理结果、做一些计算,然后发送更多查询给服务器。如果客户端和数据库服务器不在同一台机器上,所有这些会引起进程间通信并且将带来网络负担。 通过PLSQL语言,可以将一整块计算和一系列查询分组在数据库服务器内部,这样就有了一种过程语言的能力并且使SQL更易用,同时能节省的客户端/服务器通信开销。客户端和服务器之间的额外往返通信被消除。客户端不需要的中间结果不必被整理或者在服务器和客户端之间传送。多轮的查询解析可以被避免。 在当前GaussDB(DWS)的能力中主要支持两种过程化SQL语言,即基于PostgreSQL的PL/pgSQL以及基于Oracle的PL/SQL。本篇文章我们通过匿名块,函数,存储过程向大家介绍一下GaussDB(DWS)对于过程化SQL语言的基本能力。匿名块的使用 匿名块(Anonymous Block)一般用于不频繁执行的脚本或不重复进行的活动。它们在一个会话中执行,并不被存储。在GaussDB(DWS)中通过针对PostgreSQL和Oracle风格的整合,目前支持以下两种方式调用,对于Oracle迁移到GaussDB(DWS)的存储过程有了很好的兼容性支持。√ Oracle风格-以反斜杠结尾:语法格式:[DECLARE [declare_statements]] BEGIN execution_statements END; /执行用例:postgres=# DECLARE postgres-# my_var VARCHAR2(30); postgres-# BEGIN postgres$# my_var :='world'; postgres$# dbms_output.put_line('hello '||my_var); postgres$# END; postgres$# / hello world ANONYMOUS BLOCK EXECUTE√ PostgreSQL风格-以DO开头,匿名块用$$包起来:语法格式:DO [ LANGUAGE lang_name ] code;执行用例:postgres=# DO $$DECLARE postgres$# my_var char(30); postgres$# BEGIN postgres$# my_var :='world'; postgres$# raise info 'hello %' , my_var; postgres$# END$$; INFO: hello world ANONYMOUS BLOCK EXECUTE这时细心的小伙伴们就会发现,GaussDB(DWS)不仅支持了Oracle的PL/SQL的兼容性支持,对于Oracle高级包中的dbms_output.put_line函数也做了支持。所以我们也可以将两个风格混用,发现也是支持的。(^-^)Vpostgres=# DO $$DECLARE postgres$# my_var VARCHAR2(30); postgres$# BEGIN postgres$# my_var :='world'; postgres$# dbms_output.put_line('hello '||my_var); postgres$# END$$; hello world ANONYMOUS BLOCK EXECUTE函数的创建 既然匿名块GaussDB支持了Oracle和PostgreSQL两种风格的创建,函数当然也会支持两种啦。 下面我们一起来看看具体的使用吧!(。ì _ í。)√ PostgreSQL风格:语法格式:CREATE [ OR REPLACE ] FUNCTION function_name ( [ { argname [ argmode ] argtype [ { DEFAULT | := | = } expression ]} [, ...] ] ) [ RETURNS rettype [ DETERMINISTIC ] | RETURNS TABLE ( { column_name column_type } [, ...] )] LANGUAGE lang_name [ {IMMUTABLE | STABLE | VOLATILE } | {SHIPPABLE | NOT SHIPPABLE} | WINDOW | [ NOT ] LEAKPROOF | {CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT } | {[ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER | AUTHID DEFINER | AUTHID CURRENT_USER} | {fenced | not fenced} | {PACKAGE} | COST execution_cost | ROWS result_rows | SET configuration_parameter { {TO | =} value | FROM CURRENT }} ][...] { AS 'definition' | AS 'obj_file', 'link_symbol' }执行用例:定义函数为SQL查询的形式:postgres=# CREATE FUNCTION func_add_sql(integer, integer) RETURNS integer postgres-# AS 'select $1 + $2;' postgres-# LANGUAGE SQL postgres-# IMMUTABLE postgres-# RETURNS NULL ON NULL INPUT; CREATE FUNCTION postgres=# select func_add_sql(1, 2); func_add_sql -------------- 3 (1 row)定义函数为plpgsql语言的形式:postgres=# CREATE OR REPLACE FUNCTION func_add_sql2(a integer, b integer) RETURNS integer AS $$ postgres$# BEGIN postgres$# RETURN a + b; postgres$# END; postgres$# $$ LANGUAGE plpgsql; CREATE FUNCTION postgres=# select func_add_sql2(1, 2); func_add_sql2 --------------- 3 (1 row)定义返回为SETOF RECORD的函数:postgres=# CREATE OR REPLACE FUNCTION func_add_sql3(a integer, b integer, out sum bigint, out product bigint) postgres-# returns SETOF RECORD postgres-# as $$ postgres$# begin postgres$# sum = a + b; postgres$# product = a * b; postgres$# return next; postgres$# end; postgres$# $$language plpgsql; CREATE FUNCTION postgres=# select * from func_add_sql3(1, 2); sum | product -----+--------- 3 | 2 (1 row)√ Oracle风格:语法格式:CREATE [ OR REPLACE ] FUNCTION function_name ( [ { argname [ argmode ] argtype [ { DEFAULT | := | = } expression ] } [, ...] ] ) RETURN rettype [ DETERMINISTIC ] [ {IMMUTABLE | STABLE | VOLATILE } | {SHIPPABLE | NOT SHIPPABLE} | {PACKAGE} | {FENCED | NOT FENCED} | [ NOT ] LEAKPROOF | {CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT } | {[ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER | AUTHID DEFINER | AUTHID CURRENT_USER } | COST execution_cost | ROWS result_rows | SET configuration_parameter { {TO | =} value | FROM CURRENT ][...] { IS | AS } plsql_body /执行用例:定义为Oracle的PL/SQL风格的函数:实例1:postgres=# CREATE FUNCTION func_add_sql2(a integer, b integer) RETURN integer postgres-# AS postgres$# BEGIN postgres$# RETURN a + b; postgres$# END; postgres$# / CREATE FUNCTION postgres=# call func_add_sql2(1, 2); func_add_sql2 --------------- 3 (1 row)实例2:postgres=# CREATE OR REPLACE FUNCTION func_add_sql3(a integer, b integer) RETURN integer postgres-# AS postgres$# sum integer; postgres$# BEGIN postgres$# sum := a + b; postgres$# return sum; postgres$# END; postgres$# / CREATE FUNCTION postgres=# call func_add_sql3(1, 2); func_add_sql3 --------------- 3 (1 row)若想使用Oracle的PL/SQL风格定义OUT参数需要使用到存储过程,请看下面章节。存储过程的创建存储过程与函数功能基本相似,都属于过程化SQL语言,不同的是存储过程没有返回值。※ 需要注意的是目前GaussDB(DWS)只支持Oracle的CREATE PROCEDURE的语法支持,暂时不支持PostgreSQL的CREATE PROCEDURE语法支持。× PostgreSQL风格: 暂不支持。√ Oracle风格:语法格式:CREATE [ OR REPLACE ] PROCEDURE procedure_name [ ( {[ argmode ] [ argname ] argtype [ { DEFAULT | := | = } expression ]}[,...]) ] [ { IMMUTABLE | STABLE | VOLATILE } | { SHIPPABLE | NOT SHIPPABLE } | {PACKAGE} | [ NOT ] LEAKPROOF | { CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT } | {[ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER | AUTHID DEFINER | AUTHID CURRENT_USER} | COST execution_cost | ROWS result_rows | SET configuration_parameter { [ TO | = ] value | FROM CURRENT } ][ ... ] { IS | AS } plsql_body /执行用例:postgres=# CREATE OR REPLACE PROCEDURE prc_add postgres-# ( postgres(# param1 IN INTEGER, postgres(# param2 IN OUT INTEGER postgres(# ) postgres-# AS postgres$# BEGIN postgres$# param2:= param1 + param2; postgres$# dbms_output.put_line('result is: '||to_char(param2)); postgres$# END; postgres$# / CREATE PROCEDURE postgres=# call prc_add(1, 2); result is: 3 param2 -------- 3 (1 row)经过以上对GaussDB(DWS)过程化SQL语言的简单介绍,我们大致了解了在GaussDB(DWS)中匿名块,函数,存储过程的创建,下面将简单介绍一下在过程化SQL语言中的一些简单的语法介绍。基本语法介绍赋值:支持 = 与 := 两种赋值符合的使用。下面两种赋值方式都是支持的。a = b; a := b + 1;条件语句:支持IF ... THEN ... END IF; IF ... THEN ... ELSE ... END IF; IF ... THEN ... ELSEIF ... THEN ... ELSE ... END IF;其中ELSEIF也可以写成ELSIF。语法介绍:-- Case 1: IF 条件表达式 THEN --表达式为TRUE后将执行的语句 END IF; -- Case 2: IF 条件表达式 THEN --表达式为TRUE后将执行的语句 ELSE --表达式为FALSE后将执行的语句 END IF; -- Case 3: IF 条件表达式1 THEN --表达式1为TRUE后将执行的语句 ELSEIF 条件表达式2 THEN --表达式2为TRUE 后将执行的语句 ELSE --以上表达式都不为TRUE 后将执行的语句 END IF;示例:postgres=# CREATE OR REPLACE PROCEDURE pro_if_then(IN i INT) postgres-# AS postgres$# BEGIN postgres$# IF i>5 AND i<10 THEN postgres$# dbms_output.put_line('This is if test.'); postgres$# ELSEIF i>10 AND i<15 THEN postgres$# dbms_output.put_line('This is elseif test.'); postgres$# ELSE postgres$# dbms_output.put_line('This is else test.'); postgres$# END IF; postgres$# END; postgres$# / CREATE PROCEDURE postgres=# call pro_if_then(1); This is else test. pro_if_then ------------- (1 row) postgres=# call pro_if_then(6); This is if test. pro_if_then ------------- (1 row) postgres=# call pro_if_then(11); This is elseif test. pro_if_then ------------- (1 row)循环语句:支持while,for, foreach的使用。循环期间也可以适当添加循环控制语句continue, break。语法介绍:WHILE 条件表达式1 THEN --循环内需要执行的语句 END LOOP; FOR i IN result LOOP --循环内需要执行的语句 END LOOP; FOREACH var IN result LOOP --循环内需要执行的语句 END LOOP;示例:postgres=# CREATE OR REPLACE FUNCTION func_loop(a integer) RETURN integer postgres-# AS postgres$# sum integer; postgres$# var integer; postgres$# BEGIN postgres$# sum := a; postgres$# WHILE sum < 10 LOOP postgres$# sum := sum + 1; postgres$# END LOOP; postgres$# postgres$# RAISE INFO 'current sum: %', sum; postgres$# FOR i IN 1..10 LOOP postgres$# sum := sum + i; postgres$# END LOOP; postgres$# postgres$# RAISE INFO 'current sum: %', sum; postgres$# FOREACH var IN ARRAY ARRAY[1, 2, 3, 4] LOOP postgres$# sum := sum + var; postgres$# END LOOP; postgres$# postgres$# RETURN sum; postgres$# END; postgres$# / CREATE FUNCTION postgres=# call func_loop(1); INFO: current sum: 10 INFO: current sum: 65 func_loop ----------- 75 (1 row)GOTO语句:支持goto语法的使用。语法介绍:GOTO LABEL; --若干语句 <<label>>示例:postgres=# CREATE OR REPLACE FUNCTION goto_while_goto() postgres-# RETURNS TEXT postgres-# AS $$ postgres$# DECLARE postgres$# v0 INT; postgres$# v1 INT; postgres$# v2 INT; postgres$# test_result TEXT; postgres$# BEGIN postgres$# v0 := 1; postgres$# v1 := 10; postgres$# v2 := 100; postgres$# test_result = ''; postgres$# WHILE v1 < 100 LOOP postgres$# v1 := v1+1; postgres$# v2 := v2+1; postgres$# IF v1 > 25 THEN postgres$# GOTO pos1; postgres$# END IF; postgres$# END LOOP; postgres$# postgres$# <<pos1>> postgres$# /* OUTPUT RESULT */ postgres$# test_result := 'GOTO_base=>' || postgres$# ' v0: (' || v0 || ') ' || postgres$# ' v1: (' || v1 || ') ' || postgres$# ' v2: (' || v2 || ') '; postgres$# RETURN test_result; postgres$# END; postgres$# $$ postgres-# LANGUAGE 'plpgsql'; CREATE FUNCTION postgres=# postgres=# SELECT goto_while_goto(); goto_while_goto ------------------------------------------- GOTO_base=> v0: (1) v1: (26) v2: (116) (1 row)异常处理:语法介绍:[<<label>>] [DECLARE declarations] BEGIN statements EXCEPTION WHEN condition [OR condition ...] THEN handler_statements [WHEN condition [OR condition ...] THEN handler_statements ...] END; 示例:postgres=# CREATE TABLE mytab(id INT,firstname VARCHAR(20),lastname VARCHAR(20)) DISTRIBUTE BY hash(id); CREATE TABLE postgres=# INSERT INTO mytab(firstname, lastname) VALUES('Tom', 'Jones'); INSERT 0 1 postgres=# CREATE FUNCTION fun_exp() RETURNS INT postgres-# AS $$ postgres$# DECLARE postgres$# x INT :=0; postgres$# y INT; postgres$# BEGIN postgres$# UPDATE mytab SET firstname = 'Joe' WHERE lastname = 'Jones'; postgres$# x := x + 1; postgres$# y := x / 0; postgres$# EXCEPTION postgres$# WHEN division_by_zero THEN postgres$# RAISE NOTICE 'caught division_by_zero'; postgres$# RETURN x; postgres$# END;$$ postgres-# LANGUAGE plpgsql; CREATE FUNCTION postgres=# call fun_exp(); NOTICE: caught division_by_zero fun_exp --------- 1 (1 row) postgres=# select * from mytab; id | firstname | lastname ----+-----------+---------- | Tom | Jones (1 row) postgres=# DROP FUNCTION fun_exp(); DROP FUNCTION postgres=# DROP TABLE mytab; DROP TABLE总结: GaussDB(DWS)对于过程化SQL语言的支持主要在PostgreSQL与Oracle上做了兼容,同时针对Oracle的一些高级包以及一些Oracle独有的语法也做了一定支持。在迁移Oracle或者PostgreSQL时,对于函数或存储过程的迁移可以减少为了兼容导致的额外工作量。 至此已经将GaussDB(DWS)中的匿名块,函数,存储过程的创建以及基本使用介绍的差不多了。当然GaussDB(DWS)对于过程化SQL语言的支持不止如此,在接下来的时间里,还将逐步向大家介绍游标,用户自定义类型等章节哟~ヾ(◍°∇°◍)ノ゙ 想了解GuassDB(DWS)更多信息,欢迎微信搜索“GaussDB DWS”关注微信公众号,和您分享最新最全的PB级数仓黑科技,后台还可获取众多学习资料哦~原文链接:https://bbs.huaweicloud.com/blogs/265742
-
【功能模块】广东清远项目,厂商:拓维信息,租户:Hi-zhyqtalkweb02。【操作步骤&问题现象】1、创建一个fdi任务管理,从mqs中获取信息插入到mysql中,执行的时候报出SQL String cannot be empty【截图信息】
-
如图所示,在jar包运行过程中报该错误。看了下产品文档里面的错误码:通过对比同逻辑的执行模块,发现两边调用的SQL唯一的区别就是成功的只传入了一个where in (value)的值。如上图报错的则传入了多个value值。也是就select ... from table where a in ('string')和select ... from table where a in ('string1','string2','string3',...)。奇怪的是在库内直接执行报错模块的查询SQL,能正确返回目标数值。但一到虚机上运行jar包就会报如上图的错误,费解。了解到java代码里in(value)中的字符串是通过value(String)传递的,并以逗号做分割。怀疑是传参占位符有问题。求助dalao们,有没有遇到过类似问题的。
-
1. 什么是数据脱敏?什么是数据脱敏?也叫数据的去隐私化,在给定脱敏规则和策略的情况下,对敏感数据比如:身份证、手机号、卡号等,进行转换或者其他字符替换的一种技术手段,防止敏感信息直接暴露下公共的环境下。比如:政府、金融机构、移动运营商是较早开始应用数据脱敏的,原因是他们所掌握的都是用户最核心的私密数据,如果泄露对于客户是不安全的。数据脱敏的应用在生活中是比较常见的,比如我们在支付宝买页面或者某个银行App中查看账户等详情,账户信息会被用 * 遮挡,保障了商户隐私不泄露,只有点击类似眼睛的标记按钮才会全部展示完整信息!这就是一种数据脱敏方式。常见的数据脱敏:分为静态数据脱敏(SDM)和 动态数据脱敏(DDM)。1.1 静态数据脱敏 适用于将数据抽取出生产环境脱敏后分发至测试、开发、培训、数据分析等场景。有时我们可能需要将生产环境的数据迁移到测环境DB库中进行正式场景测试,以此来排查问题或进行数据分析,但出于安全考虑又不能将敏感数据存储于非生产环境,此时就要把敏感数据从生产环境脱敏完毕之后再在非生产环境使用。这样脱敏后的数据与生产环境隔离,满足业务需要的同时又保障了生产数据的安全。一般可以通过字符替换、无效化处理、重新错乱排序、加密处理等进行脱敏改造。1.2 动态数据脱敏 动态数据脱敏(DDM):一般用在生产环境,访问敏感数据时实时进行脱敏,因为有时在不同情况下对于同一敏感数据的读取,需要做不同级别的脱敏处理,例如:不同角色、不同权限所执行的脱敏方案会不同。注意:在抹去数据中的敏感内容同时,也需要保持原有的数据特征、业务规则和数据关联性,保证我们在开发、测试以及数据分析类业务不会受到脱敏的影响,使脱敏前后的数据一致性和有效性。2. 数据脱敏方案数据脱敏系统可以按照不同业务场景自行定义和编写脱敏规则,可以针对库表的某个敏感字段,进行数据的不落地脱敏。数据脱敏的方式有很多种,接下来以下图数据为准一个一个的演示每种方案。2.1 无效化无效化方案在处理待脱敏的数据时,通过对字段数据值进行 截断、加密、隐藏 等方式让敏感数据脱敏,使其不再具有利用价值。一般采用特殊字符(*等)代替真值,这种隐藏敏感数据的方法简单,但缺点是用户无法得知原数据的格式,如果想要获取完整信息,要让用户授权查询。银行很多面相外围系统就是这么脱敏的,尤其UAT环境。比如我们将身份证号用 * 替换真实数字就变成了 "220724 ****** 3523",非常简单。.2.2 随机值随机值替换,字母变为随机字母,数字变为随机数字,文字随机替换文字的方式来改变敏感数据,这种方案的优点在于可以在一定程度上保留原有数据的格式,往往这种方法用户不易察觉的。2.3 数据替换数据替换与前边的无效化方式比较相似,不同的是这里不以特殊字符进行遮挡,而是用一个设定的虚拟值替换真值。比如说我们将手机号统一设置成 “13651300000”。这个后面可以在查看原始数据时候可逆查看。2.4 对称加密对称加密是一种特殊的可逆脱敏方法,通过加密密钥和算法对敏感数据进行加密,密文格式与原始数据在逻辑规则上一致,通过密钥解密可以恢复原始数据,要注意的就是密钥的安全性。2.5 平均值平均值方案经常用在统计场景,针对数值型数据,我们先计算它们的均值,然后使脱敏后的值在均值附近随机分布,从而保持数据的总和不变。2.6 偏移和取整这种方式通过随机移位改变数字数据,偏移取整在保持了数据的安全性的同时保证了范围的大致真实性,比之前几种方案更接近真实数据,在大数据分析场景中意义比较大。比如日期字段 update_time 中 2021-05-27 10:26:25 变为 2021-01-02 15:00:00。偏移量和取整限制可以自定义。 ————————————————原文链接:https://blog.csdn.net/Mynah886/article/details/117353637
-
1)SQL是关系型数据库的标准操作语言,而SQL*PLUS是一个客户端工具,除了执行标准的SQL外,还可以执行工具本身的一些命令。2)SQL语句不可以缩写,而SQL*PLUS命令可以缩写
-
为搜索字段创建索引。避免使用 select *,列出需要查询的字段。垂直分割分表。选择正确的存储引擎。1.索引优化2.添加查询缓存3.优化数据库SQL语句4.数据库Cluster1>首先,开启慢查询global【配置文件】,(标准可以自定义),通过分析日志文件或直接show,查看哪些查询较慢.2>针对这条sql,添加Explain,查看其执行计划,查询数据条数/索引等 优化: 1.创建index索引,会占用存储空间,而且会降低DML操作的效率(做增删改需要维护索引),一般在sql中的where或者order by字段建立索引 2.通过查询缓存,可以开启Mybatis的二级缓存,自定义实现Mybatis+redis/Ehcache结合,需要注意的是,只对结果缓存,缓存结果要放在以业务逻辑相关为划分单位。缓存原则是对那些查询需求远大于增删改需求的数据 除此之外,尽量不要在where子句中使用函数,会使索引失效 如果已经确定查询结果只有一条数据(当表中数据的该字段是唯一的),在查询SQL末尾增加 limit 1 模糊查询尽量使用右模糊,左模糊会使索引失效 如果非要使用表连接,最好要保证连接的两个字段都是创建了索引的 避免使用select * 尽量使用非空 not null,可以使用‘’空串代替null。因为‘’不占用空间,null会占用空间的 在SQL语句中不要有运算,否则MySQL会放弃索引。 对于百万级以上的表数据,如果要做表连接查询,一定要对表先分页,然后对分页结果再做表连接。也可以不用表连接 nginx(负载均衡) 读写分离(MyCat) 主从复制(修改配置文件)
-
是否可以增加功能,在cpu使用率高于阈值时候自动记录运行的sql,方便后续分析
-
GaussDB 200 6.5.1.9版本有什么办法或工具能够两周查看一次慢SQL或者消耗资源比较大执行时间比较慢的SQL,能够查看并将SQL语句拉出来进行优化
-
SQL注入什么是SQL注入 程序中如果使用了未经校验的外部输入来构造SQL语句访问数据库,就很可能引入SQL注入漏洞。攻击者可以通过构造恶意输入来改变原本的SQL逻辑或者执行额外的SQL语句。如果代码使用存储过程,而这些存储过程作为包含未筛选的用户输入的字符串来传递,也会发生SQL注入。攻击原理攻击者会将一些恶意代码插入到字符串中。然后会通过各种手段将该字符串传递到数据库的实例中进行分析和执行。只要这个恶意代码符合SQL语句的规则,在代码编译与执行的时候,就不会被系统所发现。攻击者可以通过SQL注入绕过程序原有逻辑执行恶意SQL达到不法的目的。 示例用户名:tom 密码:321 正常输入: name=tom&pwd=321后端SQL: SELECT * FROM db_user WHERE NAME = 'tom' AND pwd = '321'恶意输入: name=tom’ or ‘1’ = ‘1 &pwd=111后端SQL: SELECT * FROM db_user WHERE NAME = 'tom' OR 1 = 1 AND pwd = '111' 我们可以从上面的例子看出,只要tom是有效的用户,SQL注入就可以绕开密码的验证,攻击者还可以通过通过构造恶意输入来执行代码原有逻辑以外的SQL,比如通过传入name=tom';drop table db_user-- 如果程序执行了该语句,后果可想而知后面加两个-,这意味着注释,它将后面的语句注释,让他们不起作用,这样语句永远都--能正确执行,用户轻易骗过系统,获取合法身份 如何防御 检查变量数据类型和格式固定格式的变量,比如数字,日期,邮箱,手机号等变量在SQL语句执行前严格的校验变量格式,确保变量格式规范,这样很大程度可以避免SQL注入攻击过滤特殊符号,sql语句无固定格式的变量在SQL语句执行前可以做一些特殊符号和sql语句的过滤,比如 ;,--,OR,AND等使用预编译语句a).使用PrepareStatement和占位符通过预编译sql语句防止sql注入(预编译的sql语句会带着?占位符进行编译,恶意的攻击参数无法改变已经编译好的sql语句逻辑)b). mybatis使用#{ } (#{ }会预编译,${ }则直接进行变量替换操作) 2 表达式注入什么是表达式Java统一表达式语言(英语:Unified Expression Language,简称JUEL)是一种特殊用途的编程语言,主要在Java Web应用程序用于将表达式嵌入到web页面。Java规范制定者和Java Web领域技术专家小组制定了统一的表达式语言。JUEL最初包含在JSP 2.1规范JSR-245中,后来成为Java EE 7的一部分,改在JSR-341中定义。Java中表达式根据框架分为好多种OGNL- 一个被WebWork和Apache Struts 2使用的开源的表达式语言。MVEL- 一个被众多Java项目使用的开源的表达式语言。Apache Commons JEXL - 一个旨在促进Java项目实现动态和脚本功能的开源的表达式语言。SpEL - Spring表达式语言,一个开源的EL表达式语言,是Spring Framework的一部分。它主要用于Spring portfolio项目,但也可以用于其他项目。 (摘自维基百科,https://zh.wikipedia.org/wiki/%E7%BB%9F%E4%B8%80%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%AF%AD%E8%A8%80) 什么是表达式注入 表达式根据框架分为好多种,但表达式注入的原理基本一样,表达式全部或部份外部可控从而让使用者可以通过表达式达到程序设计功能以外的能力,恶意攻击者可以通过表达式注入达到一些不法目的。 示例表达式根据框架分为好多种,这里以SpEL表达式为例。Spring Expression Language(简称SpEL)是一种强大的表达式语言,支持在运行时查询和操作对象图。语言语法类似于Unified EL,但提供了额外的功能,特别是方法调用和基本的字符串模板功能。同时因为SpEL是以API接口的形式创建的,所以允许将其集成到其他应用程序和框架中。SpEL是Spring框架中的一种语言表达式,类似于Struts2中的OGNL。 SpEL使用 #{…} 作为定界符,所有在大括号中的字符都将被认为是 SpEL表达式,我们可以在其中使用运算符,变量以及引用bean,属性和方法如:引用其他对象:#{car}引用其他对象的属性:#{car.brand}调用其它方法 , 还可以链式操作:#{car.toString()}调用其它方法 , 还可以链式操作:#{car.toString()}调用静态方法静态属性:#{T(java.lang.Math).PI}SpEL还支持许多运算符,如:算术运算符:+,-,*,/,%,^(加号还可以用作字符串连接)比较运算符:< , > , == , >= , <= , lt , gt , eg , le , ge逻辑运算符:and , or , not , |if-else 运算符(类似三目运算符):?:(temary), ?:(Elvis)正则表达式:#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}'} 图中的spel接口直接将用户输入的参数作为表达式内容进行解析,这就造成了表达式外部可控,用户可以通过input参数进行表达式注入输入 input=new ProcessBuilder("calc").start()系统执行用户传入的命令,打开了计算器。 也可以采用T() 调用一个类的静态方法,它将返回一个 Class Object,然后再调用相应的方法或属性,也是可以实现相同的功能。输入 input=T(java.lang.Math).random()常见的命令注入payload${12*12}T(java.lang.Runtime).getRuntime().exec("")T(Thread).sleep(10000)"".getClass().forName('java.lang.Runtime').getRuntime().exec("")new java.lang.ProcessBuilder({""}).start()原理SpEL内部使用了反射,可以直接获得对象的属性信息,如果SpEL表达式外部可控,同样用户可以通过表达式执行精心构造的任意代码,导致命令执行。 如何防御 尽量避免使用外部输入的内容作为EL表达式内容通过参数白名单或者黑名单控制参数的合法性如果涉及到执行表达式的方法传入的参数外部可控,就存在表达式注入的安全风险,需要通过白名单参数校验来限制 如果是java程序,需搜索检查如下关键类方法el.ExpressionFactory.createValueExpression()javax.el.ValueExpression.getValue() 指定正确EvaluationContext(针对SpEL表达式注入)Spring官方推出了SimpleEvaluationContext作为安全类来防御该类漏洞,SimpleEvaluationContext旨在仅支持SpEL语言语法的一个子集。它不包括 Java类型引用,构造函数和bean引用,指定正确EvaluationContext,是防止SpEl表达式注入漏洞产生的首选。 3 命令注入 什么是命令注入是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。在Web应用中,有时候会用到一些命令执行的函数,比如java的java.lang Runtime. Exec,php中system、exec、shell_exec等,当用户能够控制这些函数中的参数时,就可以将恶意参系统命令拼接到正常命令中,从而造成命令注入攻击 示例 输入:input=ipconfig 结果:这是一个非常简单的命令注入的例子,用户通过接口传入的参数没有经过任何处理就直接被Runtime的exec方法执行,实际上发生的命令注入漏洞时命令来源通常比较复杂,可能是程序读取的文件或是系统参数可以被用户修改,也可能是直接或是间接传入的参数,还有根据用户传入的参数进行命令拼接的。但是发生命令注入根本原因是一样的--程序执行的命令是用户可控的,通过命令的执行,应用程序会授予攻击者一种原本不该拥有的特权或能力 如果攻击者能通过命令注入漏洞获取直接执行系统命令的能力,那他基本可以获取程序拥有的所有权限,危害可想而知。 如何防御选择不调用系统命令的实现方法保证所有命令行参数的来源可控,不使用用户传入数据或者用户可以控制的数据做命令来源严格校验参数,可以使用黑白名单校验的方式控制命令的范围降低程序的权限, 参考http://rui0.cn/archives/1043https://blog.csdn.net/qq_31481187/article/details/108025512https://blog.csdn.net/weixin_41679427/article/details/110310166?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_v2~rank_aggregation-2-110310166.pc_agg_rank_aggregation&utm_term=%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E&spm=1000.2123.3001.4430
-
在GaussDB匿名块中,当有SQL发生报错时,会将整个匿名块的SQL进行回滚操作。案例:BEGIN DELETE FROM .......; --需要执行的SQL语句一; INSERT INTO LOG......; --将语句一的执行信息写入日志表,如执行时间、修改行数等。 DELETE FROM .......; --需要执行的SQL语句二; INSERT INTO LOG......; --将语句二的执行信息写入日志表EXCEPTION WHEN OTHERS THEN INSERT INTO LOG......; --将报错的SQL的信息写入日志表。END;问题:现在假如当SQL语句三报错时,SQL语句1和语句2的日志写入就会被回滚,只写入了EXCEPTION模块中的报错日志。 请问:怎么才能让匿名块中有SQL报错时,已经执行完成的操作不会被回滚。(针对单条SQL不回滚或者整个匿名块都不回滚)
-
【操作步骤&问题现象】sql及现象如下:
-
索引是对数据库表中一个或多个列的值进行排序的结构,其主要目的是提高SQL Server系统的性能,加快数据的查询速度和减少系统的响应时间。 索引表是与基本表关联的一种数据结构,它包含由基本表中的一列或多列生成的索引键和基本表中包含各个索引键的行所在的存储位置。不论基本表中是否按索引键有序,但索引中总是按索引键有序的索引的缺点索引的存在也让系统付出一定的代价,主要表现在:(1) 创建索引和维护索引要耗费时间。(2) 索引需要占用物理空间,每一个索引还要占用一定的物理空间。 (3) 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。 创建索引虽然可以提高查询速度,但是他需要牺牲一定的系统性能。因此,哪些列适合创建索引,哪些列不适合创建索引,需要进行详细的考察。索引的分类(1) 聚集索引和非聚集索引聚集索引会对基本表进行物理排序,所以这种索引对查询非常有效,在每一张基本表中只能有一个聚集索引。当建立主键约束时,如果基本表中没有聚集索引,SQL Server会用主键列作聚集索引键。 (2) 唯一索引和非唯一索引唯一索引确保在被索引的列中,所有数据都是唯一的,不包含重复的值。(3) 简单索引和复合索引只针对基本表的一列建立的索引,这种索引称为简单索引(single index)。针对多个列(最多包含16列)建立的索引称为复合索引或组合索引(composite index)。 创建索引的基本原则(1) 大量的索引,会影响INSERT、UPDATE和DELETE语句的性能。(2) 若基本表的数据量大,且对基本表的更新操作较少而查询操作较多时,可以创建多个索引来提高性能。(3) 当视图包含统计函数、表连接或两者组合时,在视图上创建索引可以显著地提高性能。(4) 可以对唯一列或非空列创建聚集索引。(5) 每个表只能创建一个聚集索引。
上滑加载中
推荐直播
-
华为云码道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华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签