在公司接手的项目碰到这么一个表,里面有一列数据保存的是JSON字符串。如果说这一列是一些配置数据,不需要应用到筛选和过滤,只是跟着主键去获得的数据,那你这么做并没有什么不妥。但事实是,这一列需要检索和过滤数据,这**居然是遍历全表,再把json数据转换成对象去遍历匹配。我服了,你咋这么能呢?喜欢这样玩为什么当初不用MongoDB?查了一下文档,知道Oracle 在12C之后有对JSON数据的操作方法,网上关于这部分的文章非常非常非常少(毕竟没几个人会把oracle当成MongoDB这么地**是吧),就整理一下,方便自己以后查看。
有一说一这官方文档非常地硬,啃了好久都啃不动,而且很多理想当然的用法都不行。Oracle中关于JSON的操作函数有JSON_ARRAY、JSON_EXISTS、JSON_VALUES、JSON_TABLE、JSON_QUERY,其中JSON_ARRAY是用来构建JSON数组的,而不是用来查找结果的。在文中也会小篇幅简单说一下用法。
JSON_EXISTS是一个SQL函数,用于判断是否存在符合条件的JSON数据。它可以在WHERE子句中使用,用于筛选JSON列中符合特定条件的数据。
官方给出的语法是这样的:
JSON_EXISTS(json_column, json_path_expression, [returning_clause])
其中,json_column是指要查询的JSON列,json_path_expression是指JSON路径表达式,用于指定要查找的JSON数据的位置和条件。
JSON路径表达式中可以使用各种操作符和函数,以及通配符和其他特殊字符。例如:
$: 表示根元素.: 表示当前元素[*]: 表示匹配数组中的所有元素[]: 表示过滤数组中符合条件的元素@: 表示当前元素的属性在json_path_expression中,可以使用一些函数,如JSON_VALUE、JSON_QUERY、JSON_TABLE等来处理JSON数据。例如:
JSON_VALUE(json_column, '$.name'): 返回json_column列中name字段的值JSON_QUERY(json_column, '$.name'): 返回json_column列中address字段的值JSON_TABLE(json_column, '$.hobbies[*]' COLUMNS (phone_number VARCHAR2(20) PATH '$')): 返回json_column列中phones数组中的所有元素的phone_number字段的值返回值:
如果符合条件的JSON数据存在,则返回TRUE;否则返回FALSE。如果使用returning_clause子句,则返回符合条件的JSON数据。
例如:
SELECT * FROM my_table WHERE JSON_EXISTS(json_data, '$.name');
这个例子查询my_table表中json_data列中是否存在name字段的值。如果存在,返回TRUE,否则返回FALSE。
JSON_ARRAY 是一个 Oracle SQL 函数,用于创建一个 JSON 数组。下面是使用 JSON_ARRAY 的一些示例:
语法:
JSON_ARRAY(value1 [, value2] [, value3] ...);
其中,value1, value2, value3 等是一个或多个要添加到 JSON 数组的值。这些值可以是任何有效的 SQL 值,例如字符串、数字、日期、布尔值等。如果没有指定任何值,JSON_ARRAY 将生成一个空的 JSON 数组。
创建一个包含两个字符串值的 JSON 数组
SELECT JSON_ARRAY('apple', 'orange') FROM dual;
输出结果:
["apple", "orange"]
创建一个包含两个数字值的 JSON 数组
SELECT JSON_ARRAY(10, 20) FROM dual;
输出结果:
[10, 20]
创建一个包含多个元素的 JSON 数组
SELECT JSON_ARRAY('apple', 10, TRUE) FROM dual;
输出结果:
["apple", 10, true]
在上述示例中,JSON_ARRAY 函数接受一个或多个参数,并将它们作为一个 JSON 数组返回。你可以在 JSON_ARRAY 中使用不同类型的参数,例如字符串,数字和布尔值,它们都将被转换为相应的 JSON 类型。
JSON_VALUE函数用于提取JSON文档中的值。它的语法如下:
JSON_VALUE(json_document, path_expression [RETURNING datatype])
其中:
json_document 是包含JSON文档的字符串或BLOB列。path_expression 是用于指定要提取的值的路径表达式。datatype 是可选的,用于指定返回值的数据类型。以下是一些示例:
提取JSON文档中的单个值:
SELECT JSON_VALUE('{"name": "John", "age": 30}', '$.name') as name FROM dual;
输出:
NAME
----
John
提取JSON文档中的数组:
SELECT JSON_VALUE('{"fruits": ["apple", "banana", "orange"]}', '$.fruits') as fruits FROM dual;
输出:
FRUITS
-----------------------
["apple", "banana", "orange"]
提取JSON文档中的数组元素:
SELECT JSON_VALUE('{"fruits": ["apple", "banana", "orange"]}', '$.fruits[0]') as first_fruit FROM dual;
输出:
FIRST_FRUIT
-----------
apple
指定返回值的数据类型:
SELECT JSON_VALUE('{"price": 9.99}', '$.price' RETURNING NUMBER) as price FROM dual;
输出:
PRICE
-----
9.99
在使用JSON_VALUE函数时,需要注意以下几点:
JSON_QUERY函数用于从JSON文档中查询数据,返回一个JSON对象或数组。它的语法如下:
JSON_QUERY(json_document, path_expression [RETURNING datatype])
其中:
json_document 是包含JSON文档的字符串或BLOB列。path_expression 是用于指定要查询的值的路径表达式。datatype 是可选的,用于指定返回值的数据类型。以下是一些示例:
SELECT JSON_QUERY('{"name": "John", "age": 30}', '$.name') as name FROM dual;
输出:
NAME
----
null
SELECT JSON_QUERY('{"fruits": ["apple", "banana", "orange"]}', '$.fruits') as fruits FROM dual;
输出:
FRUITS
-----------------------
["apple", "banana", "orange"]
SELECT JSON_QUERY('{"fruits": ["apple", "banana", "orange"]}', '$.fruits[0]') as first_fruit FROM dual;
输出:
FIRST_FRUIT
-----------
null
因为是单值,json_query无法展示
在使用JSON_QUERY函数时,需要注意以下几点:
总之,JSON_QUERY函数在处理JSON文档时非常有用,可以轻松地查询和提取需要的数据。
JSON_TABLE函数可以将JSON数据转换为表格形式。以下是JSON_TABLE的用法:
语法:
JSON_TABLE(json, path COLUMNS (column1 expr1 [, column2 expr2]...))
参数说明:
json:要转换的JSON数据。path:要提取的JSON元素的路径。COLUMNS:指定要转换的列及其表达式。column1 expr1 [, column2 expr2]...:指定要转换的列及其表达式。示例:
假设我们有以下JSON数据:
{
"employees": [
{ "name": "John", "age": 30, "gender": "male" },
{ "name": "Jane", "age": 25, "gender": "female" },
{ "name": "Bob", "age": 35, "gender": "male" }
]
}
我们可以使用以下查询将其转换为表格形式:
SELECT name, age, gender
FROM JSON_TABLE('{
"employees": [
{ "name": "John", "age": 30, "gender": "male" },
{ "name": "Jane", "age": 25, "gender": "female" },
{ "name": "Bob", "age": 35, "gender": "male" }
]
}', '$.employees[*]' COLUMNS (
name VARCHAR2(50) PATH '$.name',
age NUMBER PATH '$.age',
gender VARCHAR2(10) PATH '$.gender'
));
输出结果:
NAME AGE GENDER
------ ---- ------
John 30 male
Jane 25 female
Bob 35 male
在上面的例子中,$.employees[*]指定要处理的JSON元素路径,name, age, 和 gender 列使用 PATH 关键字指定表达式的路径。
我举个实际的例子,我有一列,对应的一列的数据大概是这样的:
{
"name": "cxk", // string
"sex": "female", // stirng
"hobbies": ["sing", "dance", "rap", "basketball"], // 普通数组
"company": {"name": "unknow", "staffNum": "unknow"}, // 对象属性
"fans": [ // 对象数组
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}
看了前面的介绍,可能有些同学对这个完全不能理解,有什么区别?
select JSON_QUERY
('{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"},
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}', '$.name'
) as json_query_res,
JSON_VALUE
('{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"},
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}', '$.name'
) as json_value_res
from dual;
输出结果:
JSON_QUERY_RES JSON_VALUE_RES
--------------------------------
null cxk
区别1:json_query无法返回单值,json_value可以返回单值
select JSON_QUERY
('{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"},
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}', '$.company'
) as json_query_res,
JSON_VALUE
('{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"},
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}', '$.company'
) as json_value_res
from dual;
输出结果:
JSON_QUERY_RES JSON_VALUE_RES
-------------------------------- ------------------
{"name": "unknow", "staffNum": "unknow"} null
区别2:json_query能返回对象,json_value不能返回对象值
select JSON_QUERY
('{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"},
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}', '$.hobbies'
) as json_query_res,
JSON_VALUE
('{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"},
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}', '$.hobbies'
) as json_value_res
from dual;
输出结果:
JSON_QUERY_RES JSON_VALUE_RES
-------------------------------- ------------------
["sing", "dance", "rap", "basketball"] null
区别3:json_query能返回普通数组,json_value不能返回数组
select JSON_QUERY
('{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"}
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}', '$.hobbies[0]'
) as json_query_res,
JSON_VALUE
('{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"}
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}', '$.hobbies[0]'
) as json_value_res
from dual;
输出结果:
JSON_QUERY_RES JSON_VALUE_RES
-------------------------------- ------------------
null sing
select JSON_QUERY
('{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"},
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}', '$.fans'
) as json_query_res,
JSON_VALUE
('{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"},
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}', '$.fans'
) as json_value_res
from dual;
输出结果:
JSON_QUERY_RES JSON_VALUE_RES
-------------------------------- ------------------
[{"name": "ncFans1"},{"name": "ncFans2"}] null
区别4:JSON_QUERY可以匹配对象数组的值,JSON_VALUE不可以
这是比较难的一个步骤,我自己摸索了很久很久才懂,我这里举例都写到了谓动词的位置,实际上JSON_EXISTS是用在where后的。
SELECT case when JSON_EXISTS('{"name": "John", "age": 30, "city": "New York"}', '$.name') then 'true' else 'false' end as result FROM dual;
输出:
RESULT
---------
true
但其实,我们更多都是在匹配name值等于具体的值,这就要用匹配的机制,但愿你还记得前面介绍的用法
SELECT case when JSON_EXISTS('
{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"}
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}
', '$.name ? (@ == "cxk")') then 'true' else 'false' end as result FROM dual;
@表示当前name属性这一层,值一定要用双引号括起来
SELECT case when JSON_EXISTS('
{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"}
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}
', '$.company ? (@.name == "unknow" && @.staffNum == "unknow")') then 'true' else 'false' end as result FROM dual;
select * from mytable where
JSON_EXISTS(my_cloumn, '$.name ? (@ == "cxk")')
AND
JSON_EXISTS(my_cloumn, '$.company ? (@.name == "unknow" && @.staffNum == "unknow")')
SELECT case when JSON_EXISTS('
{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"}
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}
',
'$.hobbies[*] ? (@ == "sing")')
then 'true' else 'false' end as result FROM dual;
执行结果为true
SELECT case when JSON_EXISTS('
{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"}
"fans": [
{"name": "ncFans1"},
{"name": "ncFans2"}
]
}
',
'$.fans")')
then 'true' else 'false' end as result FROM dual;
无论是$.fans还是$.fans[*]返回结果都是false,完全无法获取对象数组中的值。无法判断里面的值的对比情况。
SELECT case when JSON_EXISTS('
{
"name": "cxk",
"sex": "female",
"hobbies": ["sing", "dance", "rap", "basketball"],
"company": {"name": "unknow", "staffNum": "unknow"}
"fans": []
}
',
'$.fans")')
then 'true' else 'false' end as result FROM dual;
但如果是$.fans[0]返回的是false
$.xx中不能用字符串拼接、不能用任何函数会报ORA-40442错误select * from mytable where
JSON_VALUE(my_cloumn, '$.name') = 'cxk'
and
JSON_QUERY(my_cloumn, '$.fans') = '[]' -- 判空
$.fans,不需要$.fans[*];支持使用下标指定SELECT * from mytable where
JSON_VALUE(JSON_QUERY(my_cloumn, '$.fans'), '$.name') = 'ncFans1'
这个语句就是查找出fans中有ncFans1的记录
select * from mytable where
JSON_QUERY(my_cloumn, '$.fans') = '[]'
select * from mytable where
not JSON_EXISTS(my_cloumn, '$.fans[0]')
$.xx的语句要放在单引号中',切不能使用任何函数,不能字符拼接,所以用#{}无法注入,要用${},这在有些公司是不被允许的。目前我是这么用了,等安全部门的渗透测试结果出来,是否有sql注入风险再来更新。以上提到的操作均需要在Oracle12以上版本中使用,但并不是12以上版本都能使用。这个和数据库设置的compatible值有关。compatible必须大于12.0才可以使用。
你可以使用拥有DBA权限的用户执行以下语句查看compatible值
SELECT name, value FROM v$parameter WHERE name = 'compatible'
否则,你会得到这样的一个报错
ORA-00406: COMPATIBLE parameter needs to be 12.0 or greater
然后你就白忙活了,因为一般都不会为了你特地升级compatible的。没事,我就是白忙活了。
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf