Parsing JSON to relational Table using ORDS - oracle

I want to parse and insert below JSON to relational table using PL/SQL & ORDS. but I'm stuck at sizes part of below JSON
{
"order_number": "302523001",
"sizes": {
"34": 2,
"33": 4,
"32": 7,
"36": 8
}
}
I am using below code to process above
INSERT INTO test_sizes_tbl
SELECT * FROM json_table
(l_po format json, '$' COLUMNS (
order_number varchar2 path '$.order_number',
NESTED path '$.sizes[*]'
COLUMNS (
size_name varchar2 path '$.key',
size_value varchar2 path '$.value')));
Sizes e.g. 32, 33, 34, 36 are dynamic values and there is no way to fix them as key. I need to pick these sizes dynamically and insert into table. How to parse above JSON?

Related

i got a error ORA-01747 when insert data into table

i got trouble when insert data using this query :
INSERT ALL
INTO obat ('id_obat','nama_obat','tanggal_kadarluarsa','stock','harga')
VALUES (1, 'Indomethacin', '2023-09-01', 50, 3000)
SELECT * FROM dual;
this is the table query :
CREATE TABLE obat (
id_obat INTEGER NOT NULL,
nama_obat VARCHAR2(255) NOT NULL,
tanggal_kadarluarsa DATE NOT NULL,
stock INTEGER NOT NULL,
harga NUMBER(20, 2) NOT NULL,
CONSTRAINT obat_pk PRIMARY KEY ( id_obat )
);
is somethin wrong with my code?
Single quotes are for string literals; identifiers (e.g. column names) should be in double quotes - but only have to be if they were created as quoted identifiers, and then the case of the name has to match the data dictionary name exactly. Yours are not quoted identifiers in the create statement, so you can just do:
INSERT ALL
INTO obat (id_obat,nama_obat,tanggal_kadarluarsa,stock,harga)
VALUES (1, 'Indomethacin', DATE '2023-09-01', 50, 3000)
SELECT * FROM dual;
If you really wanted to quote them then you would need to do (including the table name to demonstrate, as the same rules apply):
INSERT ALL
INTO "OBAT" ("ID_OBAT","NAMA_OBAT","TANGGAL_KADARLUARSA","STOCK,HARGA")
VALUES (1, 'Indomethacin', DATE '2023-09-01', 50, 3000)
SELECT * FROM dual;
but that's just more typing and arguably maybe harder to read, and easier to get wrong.
You can read more about quoted and non-quoted identifiers in the documentation.
With a single row you don't really need ALL, you can also do:
INSERT INTO obat (id_obat,nama_obat,tanggal_kadarluarsa,stock,harga)
VALUES (1, 'Indomethacin', DATE '2023-09-01', 50, 3000)
Note that I've added the DATE keyword to these statements; '2023-09-01' is not a date, it's a string literal, so you're relying on Oracle implicitly converting that to an actual date, based on your current session NLS settings. With DATE '2023-09-01' that is now a date literal. Again, there is more in the documentation.

query object attributs (as data in a column) Oracle SQL

I imported a dataset that has a object in the column GENRES and I'm wondering if there is a (beginner's) way to query the data inside each entry.
[{"id": 12, "name": "Adventure"}, {"id": 10751, "name": "Family"}, {"id": 14, "name": "Fantasy"}]
For example, if I would want to query all the movies having the "id": 12.
The dataset comes from here
If you store the data with an IS JSON constraint, then you can use JSON_TABLE to expand the JSON into columns.
--Create a table.
create table tmdb(movie_id number, genres clob check (genres is json));
--Insert a test row.
insert into tmdb
values(1, '[{"id": 12, "name": "Adventure"}, {"id": 10751, "name": "Family"}, {"id": 14, "name": "Fantasy"}]');
--Use JSON_TABLE to convert JSON to relational data.
select movie_id, id, name
from tmdb,
json_table
(
genres, '$[*]'
columns
(
id number path '$.id',
name varchar2(4000) path '$.name'
)
) as jt;
--Results:
MOVIE_ID ID NAME
-------- ----- ---------
1 12 Adventure
1 10751 Family
1 14 Fantasy

Mapping generic JSON field with Redshift Spectrum

I am trying to cast a variable type JSON field in Redshift Spectrum as a plane string but keep getting column type VARCHAR for column STRUCT is incompatible.
The JSON data I am trying to query has several fields which structure is fixed and expected. However there is one field with metadata which is a JSON with no specific format (anything is valid). For example:
{"fixed_integer": 1, "fixed_date": "2019-01-01", "metadata": {"one": "two", "three": 4}}
{"fixed_integer": 1, "fixed_date": "2019-01-01", "metadata": {"five": [1, 2], "six": false}}
I can map the code with the DDL as
CREATE EXTERNAL TABLE my_data(
fixed_integer int,
fixed_date varchar,
metadata varchar
)
without complaints, but when I try to query the data with a simple SELECT metadata FROM my_data I get
declared column type VARCHAR for column STRUCT is incompatible.
I could not find a workaround for it so far.
Have anyone faced a this or a similar problem?
Metadata field it's not a valid varchar, to be a valid varchar field it should look like this
"metadata": '{"one": "two", "three": 4}}'
which is not a correct json format
I think if you create your external table with metadata as struct you can query it
CREATE EXTERNAL TABLE my_data(
fixed_integer int,
fixed_date varchar,
metadata struct <details:varchar(4000)>
)
row format serde 'org.openx.data.jsonserde.JsonSerDe'
with serdeproperties (
'dots.in.keys' = 'true',
as location '<s3 location>'
While you query metadata field you need to specify .
SELECT metadata.details FROM my_data
Let me know if this works for you.

Vertica: Parse string as JSON when inserting data from table into flextable

I use Vertica 9.2.1 in EON-mode.I have a fact table with a column that holds JSON strings. I want to load this data together with some identifiers from the fact table into a flextable. So that we can run analysis on that data. What I want to avoid is, loading all the necessary data onto an ETL machine to transform the data and then load it into the flextable, since all the data is already available in Vertica. How can I tell Vertica to parse a VARCHAR column as JSON?
CREATE TABLE public.tmp_facts ("id" INTEGER, "user_id" VARCHAR(64), "event_type" VARCHAR(50), /* other columns omitted */ "additional" VARCHAR(65000));
INSERT INTO public.tmp_facts ("id", "user_id", "event_type", "additional")
SELECT 1, 'user1', 'event1', '{"os":"Android", "time":"'||NOW()||'"}';
CREATE FLEX TABLE public.fact_additional
(
"id" INTEGER NOT NULL,
"user_id" VARCHAR(64) NOT NULL,
"event_type" VARCHAR(50)
);
INSERT INTO public.fact_additional ("id", "user_id", "event_type")
SELECT "id", "user_id", "event_type", "additional" FROM tmp_facts;
SELECT "additional", "additional.os", "additional[os]" FROM fact_additional;
I expected that the last query outputs for at least one column Android
You need to pass the additional column through MapJSONExtractor() function when inserting from public.tmp_facts into public.fact_additional
INSERT INTO public.fact_additional ("id", "user_id", "event_type")
SELECT "id",
"user_id",
"event_type",
MapJSONExtractor("additional") as additional
FROM tmp_facts;
SELECT "additional"['os'] as os FROM fact_additional;
os
---------
Android
(1 row)
Notice the usage of single / double quotes at the appropriate places.

Oracle table naming causes issues when inserting data

In Oracle 12c, I had a table named "CONTAINERS" and the following query was failing to insert data.
insert into CONTAINERS (ID,CONTAINER_NAME, HIERARCHY_SUB_TYPES_ID, HIERARCHY_TYPES_ID, SEGMENT_ID, SUB_SEGMENT_ID, USERS_ID_HIERARCHY_OWNER)
values (44,'ContainerName', 1, 1, 1, 1, 1);
Error:
Error at Command Line : 1 Column : 28 Error report - SQL Error:
ORA-02000: missing ) keyword
02000. 00000 - "missing %s keyword"
But this worked successfully
insert into CONTAINERS values (3,'ContainerName', 1, 1, 1, 1, 1);
I had to rename the table from "CONTAINERS" to "CONTAINER" for everything to work normally.
Can someone explain why I got this behavior?
DDL:
CREATE TABLE "RELANDHIER"."CONTAINERS"
( "ID" NUMBER,
"CONTAINER_NAME" VARCHAR2(200 BYTE),
"USERS_ID_HIERARCHY_OWNER" NUMBER,
"SEGMENT_ID" NUMBER,
"SUB_SEGMENT_ID" NUMBER,
"HIERARCHY_TYPES_ID" NUMBER,
"HIERARCHY_SUB_TYPES_ID" NUMBER
)
"CONTAINERS" seems to be a "reserved name". Here is my test case derived from yours :
drop table "DEMO"."CONTAINERS";
CREATE TABLE "DEMO"."CONTAINERS"
( "ID" NUMBER,
"CONTAINER_NAME" VARCHAR2(200 BYTE),
"USERS_ID_HIERARCHY_OWNER" NUMBER,
"SEGMENT_ID" NUMBER,
"SUB_SEGMENT_ID" NUMBER,
"HIERARCHY_TYPES_ID" NUMBER,
"HIERARCHY_SUB_TYPES_ID" NUMBER
);
insert into CONTAINERS (ID,CONTAINER_NAME, HIERARCHY_SUB_TYPES_ID, HIERARCHY_TYPES_ID, SEGMENT_ID, SUB_SEGMENT_ID, USERS_ID_HIERARCHY_OWNER)
values (44,'ContainerName', 1, 1, 1, 1, 1);
insert into "DEMO".CONTAINERS (ID,CONTAINER_NAME, HIERARCHY_SUB_TYPES_ID, HIERARCHY_TYPES_ID, SEGMENT_ID, SUB_SEGMENT_ID, USERS_ID_HIERARCHY_OWNER)
values (44,'ContainerName', 1, 1, 1, 1, 1);
INSERT only works if I prefix the owner schema to it.
Execution gives :
Table dropped.
Table created.
insert into CONTAINERS (ID,CONTAINER_NAME, HIERARCHY_SUB_TYPES_ID, HIERARCHY_TYPES_ID, SEGMENT_ID, SUB_SEGMENT_ID, USERS_ID_HIERARCHY_OWNER)
*
ERROR at line 1:
ORA-02000: missing ) keyword
1 row created.
Check this link to Oracle 12c new features

Resources