详细信息: Oracle数据库12c, 数据库版本:12.1.0.2.0
问题描述和要求:
第1部分:
使用BLOB列上的JSON文本搜索索引进行搜索时,与NCLOB上的简单查询(LIKE)相比,性能得到了显着提高。
关于JSON搜索索引:
JSON搜索索引是一种专门用于JSON数据的全文本索引。 如果数据库使用字符集AL32UTF8或WE8ISO8859P1 ,并且仅针对VARCHAR2,BLOB或CLOB列中的JSON数据,而不使用NVARCHAR2和NCLOB列,则优化器将仅考虑使用索引。 / strong>。
第2部分:
我们有两种数据库类型,即单字节和多字节部署
单个字节的字符集:
NLS_NCHAR_CHARACTERSET ---> AL16UTF16, NLS_CHARACTERSET ---------> WE8MSWIN1252
多字节字符集:
NLS_NCHAR_CHARACTERSET ---> AL16UTF16, NLS_CHARACTERSET ---------> AL32UTF8
第3部分:
在多字节部署中,我能够存储和搜索(使用JSON_TEXTCONTAINS)多字节文本,例如'məharaːʂʈrə'。 原因:因为数据库使用字符集AL32UTF8(BLOB列) 注意:JSON_TEXTCONTAINS仅适用于索引。
在单字节部署中,我无法存储相同的文本,即“məharaːʂʈrə”(由于它是多字节,因此转换会导致数据丢失,例如“ m?hara ??? r?”)
问题: 如何在具有字符集WE8MSWIN1252的单字节部署的BLOB列中存储多字节数据,即“məharaːʂʈrə”。
如oracle所述:如果数据库使用 AL32UTF8或WE8ISO8859P1字符集,则优化器将仅考虑使用索引。 请注意,我也可以在单字节环境中使用JSON搜索索引,即JSON_TEXTCONTAINS(用于简单搜索,即单字节)。
一旦我能够按原样存储数据,就可以使用JSON_TEXTCONTAINS进行搜索。
示例代码(在单字节和多字节部署中都尝试: 请注意:https://livesql.oracle.com/是多字节部署。
创建表:
create table departments_json (
department_id integer not null primary key,
department_data blob not null
);
数据应为严格的Json(因此我们可以使用点符号进行遍历):
alter table departments_json
add constraint dept_data_json
check ( department_data is JSON FORMAT JSON STRICT );
创建索引:
create index deptj_ctx_ix
on departments_json (department_data)
indextype is ctxsys.context parameters ('section group CTXSYS.JSON_SECTION_GROUP sync (on commit)');
插入简单的json
insert into departments_json
values ( 140, utl_raw.cast_to_raw ('{"department_list":[{"Deptname":"DEPT-A", "value" : "məharaːʂʈrə"}]}'));
如果有任何错误(以单字节为单位),请将其转换:
insert into departments_json
values ( 140, UTL_RAW.convert(utl_raw.cast_to_raw ('{"department_list":[{"Deptname":"DEPT-A", "value" : "məharaːʂʈrə"}]}'),'AL32UTF8','WE8MSWIN1252'));
存储的值:
SELECT json_value(department_data format json, '$.department_list.value' ) FROM departments_json JS WHERE DEPARTMENT_ID=140;
观察:在单字节环境中将导致数据丢失。
现在搜索:
SELECT *
FROM departments_json
WHERE JSON_TEXTCONTAINS(department_data, '$.department_list.value', 'məharaːʂʈrə');
观察:多字节将导致行,而单字节将导致无行。
还可以在单字节环境中使用JSON搜索索引,即JSON_TEXTCONTAINS(用于简单搜索,即单字节)-在查询结果下方一行:
SELECT *
FROM departments_json
WHERE JSON_TEXTCONTAINS(department_data, '$.department_list.Deptname', 'DEPT-A');
答案 0 :(得分:0)
您可以通过.NET(C#)保存数据:
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var value = System.Text.Encoding.GetEncoding("windows-1252").GetString(System.Text.Encoding.UTF8.GetBytes("məharaːʂʈrə"));
string h = "{\"department_list\":[{\"Deptname\":\"DEPT-A\", \"value\" : \"" + value + "\"}]}";
var byteArraySource = System.Text.Encoding.Unicode.GetBytes(h);
byte[] byteArray = System.Text.Encoding.Convert(System.Text.Encoding.Unicode,
System.Text.Encoding.UTF8, byteArraySource);
using (var orclCon = new Oracle.ManagedDataAccess.Client.OracleConnection(connectionString))
{
orclCon.Open();
var cmd = orclCon.CreateCommand();
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "insert into departments_jsonvalues (140, :paramValue)";
cmd.Parameters.Add(new Oracle.ManagedDataAccess.Client.OracleParameter("paramValue", Oracle.ManagedDataAccess.Client.OracleDbType.Blob, byteArray, System.Data.ParameterDirection.Input));
cmd.ExecuteNonQuery();
}
对于.NET中的搜索结果:
string h ="məharaːʂʈrə";
var read_command = orclCon.CreateCommand();
read_command.CommandType = System.Data.CommandType.Text;
read_command.Parameters.Add(new Oracle.ManagedDataAccess.Client.OracleParameter("searchText", System.Text.Encoding.GetEncoding("windows-1252").GetString(System.Text.Encoding.UTF8.GetBytes(h))));
read_command.CommandText = "select * from departments_json JSON_TEXTCONTAINS(department_data, '$.department_list.value', :searchText)";
var dr = read_command.ExecuteReader();
using (dr)
{
if (dr.HasRows)
{
while (dr.Read())
{
Oracle.ManagedDataAccess.Types.OracleBlob BLOB = dr.GetOracleBlob(1);
var sr = new System.IO.StreamReader(BLOB);
var content = sr.ReadToEnd();
}
}
}
插入SQL:
insert into departments_json values (140, utl_raw.cast_to_raw ('{"department_list":[{"Deptname":"DEPT-A", "value" :'|| UTL_RAW.convert("məharaːʂʈrə",'UTF8','WE8MSWIN1252')||'}]}'));
SQL搜索结果:
SELECT * FROM departments_json WHERE JSON_TEXTCONTAINS(department_data, '$.department_list.value', CONVERT('məharaːʂʈrə', 'UTF8', 'WE8MSWIN1252'));