Oracle 12c JSON Query Issue with Dot Notation and Double Quotes - json

I have a table "EvMetadata" with column "Metadata" that has a check constraint of "IS JSON". Note that the table and its columns are created with DOUBLE QUOTES by design.
Following SQL works where I'm not specifying any JSON work to be done by Oracle.
select
m."Metadata"
from "EvMetadata" m
As you can see below, the Metadata column simply displays its content which happens to be JSON data.
However, I get error if I were to issue a json query as follows.
select
m."Metadata"."FileName"
from "EvMetadata" m
I just added "FileName" using dot notation. As you can see above, "FileName" is a valid json field. So why the error?
Error is
ORA-00904: "M"."Metadata"."FileName": invalid identifier 00904. 00000 - "%s: invalid identifier" *Cause: *Action: Error at Line: 2 Column: 3
Could this be a bug with Oracle's JSON query support using the dot notation under a specific scenario where database objects are declared with double quotes? The reason I suspect that may be true is that the following equivalent query, not using the dot notation, works.
select
JSON_VALUE(m."Metadata", '$.FileName')
from "EvMetadata" m

You need to have an "IS JSON" check constraint on the column for dot notation to work:
Here's an excerpt from the documentation:
Each json_key must be a valid SQL identifier, and the column must have an is json check constraint, which ensures that it contains well-formed JSON data. If either of these rules is not respected then an error is raised at query compile time. (The check constraint must be present to avoid raising an error; however, it need not be active. If you deactivate the constraint then this error is not raised.)
Here's a test example I did to verify this is how it's working:
--create a table to put stuff in
create table foo (
json varchar2(4000)
);
--------------------------------
Table FOO created.
--insert test value
insert into foo(json) values('{"attr1":5,"attr2":"yes"}');
commit;
--------------------------------
1 row inserted.
Commit complete.
--try some selects
--no table alias, no constraint, borked
select json.attr1 from foo;
--------------------------------
Error starting at line : 12 in command -
select json.attr1 from foo
Error at Command Line : 12 Column : 8
Error report -
SQL Error: ORA-00904: "JSON"."ATTR1": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
--with table alias, no constraint, borked
select a.json.attr1 from foo a;
--------------------------------
Error starting at line : 15 in command -
select a.json.attr1 from foo a
Error at Command Line : 15 Column : 8
Error report -
SQL Error: ORA-00904: "A"."JSON"."ATTR1": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
--add our constraint
alter table foo add constraint json_isjson check (json is json);
--------------------------------
Table FOO altered.
--no table alias, with constraint, borked
select json.attr1 from foo;
--------------------------------
Error starting at line : 21 in command -
select json.attr1 from foo
Error at Command Line : 21 Column : 8
Error report -
SQL Error: ORA-00904: "JSON"."ATTR1": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
--table alias and constraint, works!
select a.json.attr1 from foo a;
--------------------------------
ATTR1
--------------------------------------------------------------------------------
5

In case anyone else gets this issue, its documented in Oracle Support under note 2192052.1
Basically, it's a bug whereby Dot Notation doesn't work on a column which is created with a NOT NULL constraint, i.e.
If you do:
CREATE TABLE foo.bar (id NUMBER NOT NULL, json_doc CLOB NOT NULL CHECK (json_doc IS JSON));
you'll get the error when you run:
SELECT a.json_doc.elementName FROM foo.bar a;
but if you do:
CREATE TABLE foo.bar (id NUMBER NOT NULL, json_doc CLOB CHECK (json_doc IS JSON));
ALTER TABLE bar MODIFY (json_doc NOT NULL);
the Dot notation will work.

You do not need quotes, this shall work:
select m.Metadata.FileName from EvMetadata m
Please refer to the example of official documentation:
SELECT po.po_document.PONumber FROM j_purchaseorder po;
SELECT json_value(po_document, '$.PONumber') FROM j_purchaseorder;

Related

confused by oracle error msg : PL/SQL: ORA-25137: Data value out of range

An error(PL/SQL: ORA-25137: Data value out of range ) was reported when I executed the following code in Oracle 21c.
create table t(id int ,j json);
insert into t values(1,'{"key":"valus"}');
DECLARE
b varchar2(100);
BEGIN
select cast(j as varchar2(100)) into b from t where id=1;
DBMS_OUTPUT.PUT_LINE(b);
END;
The error message is
ERROR at line 4:
ORA-06550: line 4, column 15:
PL/SQL: ORA-25137: Data value out of range
ORA-06550: line 4, column 3:
PL/SQL: SQL Statement ignored
The oracle version I used is
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production Version 21.3.0.0.0
I can't understand why this error was reported.
I think the cast target size I set is enough, but "ORA-25137: Data value out of range" was reported.
Can anyone explain why?
The data is stored in the table in binary format so you should use JSON_SERIALIZE function to convert JSON from any supported type into text. It is available since 19c:
Select t.id, json_serialize(t.j) From tbl t;
id j
---- -------------------
1 {"key":"valus"}
or, for previous versions use some of json functions like:
Select t.id, json_value(t.j, '$.key') as json_key From tbl t;
id json_key
---- -------------------
1 valus
There are more functions and options to get your data using sql with json datatype (json_query(), json_table(), ...)
You can find more about it -- https://oracle-base.com/articles/21c/json-data-type-21c

Teradata Table creation throwing an error: Syntax error: expected something between the 'TABLE' keyword and the 'PUBLIC' keyword

I am connected to Teradata via the dbeaver. I successfully got connected to it after downloading the libraries from the https://downloads.teradata.com/. I am completely new to teradata. I copied one command from the tutorials point and tried to ran it.
CREATE SET TABLE PUBLIC.EMPLOYEE,FALLBACK (
EmployeeNo INTEGER,
FirstName VARCHAR(30),
LastName VARCHAR(30),
DOB DATE FORMAT 'YYYY-MM-DD',
JoinedDate DATE FORMAT 'YYYY-MM-DD',
DepartmentNo BYTEINT
)
UNIQUE PRIMARY INDEX ( EmployeeNo );
But I keep getting the error:
SQL Error [3706] [42000]: [Teradata Database] [TeraJDBC 16.20.00.06] [Error 3706] [SQLState 42000] Syntax error: expected something between the 'TABLE' keyword and the 'PUBLIC' keyword.
I even tried creating the table form the dbeaver UI then still it is giving me an error. If someone could help me I will really appreciate it.

Programming Error while creating MySQL Table

#I am translating input from a user into a MySQL command but it says i have the syntax wrong and Idk how I can fix it. Essentially I made a program in python (not a problem with the python code) that has the ability to create MySQL tables and translates user input into a MySQL command to create the table, but I think i have worded the command wrong and need someone to help explain what I did wrong and how I can fix it or another way to do it (no new python packages just different MySQL command).
#Error
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''c1', 'c2') VALUES [('r1', 'r2')]' at line 1
#here is what i was collecting in my attempt to fix the bug
'''
ROW SYNTAX: [('r1', 'r2')]
COLUMN SYNTAX: ('c1', 'c2')
MySQL COMMAND: CREATE TABLE test ('c1', 'c2') VALUES [('r1', 'r2')]
'''
#just the values none of the ROW SYNTAX or COLUMN SYNTAX is actually put into the mysql command
I was expecting it to create the table with:
2 columns: c1 and c2
1 row with 2 values: r1 and r2
Yet as I have explained above... it doesn't. I don't work with MySQL just python really so I'm probably missing something really easy or big that I just don't understand.
i've seen some example syntax similar to this but again I don't understand it.
UPDATE
'''
ROW SYNTAX: [('r1', 'r3'), ('r2', 'r4')]
COLUMN SYNTAX TCOLN: (c1, c2)
COLUMN SYNTAX COLNAMES: (c1 VCHAR(255), c2 VCHAR(255))
CREATE TABLE COMMAND: CREATE TABLE test (c1 VCHAR(255), c2 VCHAR(255));
INSERT TABLE COMMAND: INSERT INTO test (c1, c2) VALUES [('r1', 'r3'), ('r2', 'r4')];
'''
'''
Traceback (most recent call last):
line 472, in cmd_query
raw_as_string=raw_as_string)
_mysql_connector.MySQLInterfaceError: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VCHAR(255), c2 VCHAR(255))' at line 1
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
line 558, in ctable
cursor.execute(sqlCol) #slqCol is CREATE TABLE test (c1 VCHAR(255), c2 VCHAR(255));
line 266, in execute
raw_as_string=self._raw_as_string)
line 475, in cmd_query
sqlstate=exc.sqlstate)
mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VCHAR(255), c2 VCHAR(255))' at line 1
'''
Thanks to your suggestions i am using VARCHAR now but i still seem to be running into close to the same problem
Thanks to #Martin for explaining what varchar is ect, it also turns out VCHAR is not the same as VARCHAR (thanks #robsiemb). Now the table is creating BUT not putting the data values in? (this might be a python problem, hope not)
'''
INSERT TABLE COMMAND: INSERT INTO test (c1, c2) VALUES ('r1', 'r2'),('rr1', 'rr2');
'''
# LATEST UPDATE
New Error when inserting values
```python
#CREATE TABLE COMMAND: CREATE TABLE test (c1 VARCHAR(255), c2 VARCHAR(255));
#INSERT TABLE COMMAND: INSERT INTO test (c1, c2) VALUES (r1,r3),(r2,r4);
'''
Traceback (most recent call last):
line 472, in cmd_query
raw_as_string=raw_as_string)
_mysql_connector.MySQLInterfaceError: Unknown column 'r1' in 'field list'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
line 563, in ctable
cursor.execute(sqlVal)
line 266, in execute
raw_as_string=self._raw_as_string)
line 475, in cmd_query
sqlstate=exc.sqlstate)
mysql.connector.errors.ProgrammingError: 1054 (42S22): Unknown column 'r1' in 'field list'
'''
Python problem, thanks for answering my question!
The problem with what you are doing is in this statement:
CREATE TABLE test ('c1', 'c2') VALUES [('r1', 'r2')]
This is not a valid CREATE TABLE statement.
It looks like you're trying to create the table, and then insert some values into it. Is that the case?
If so, this should be broken into two statements. First create the table:
CREATE TABLE test (c1 DATATYPE, c2 DATATYPE);
Replace DATATYPE with the type of the column you are creating (i.e. INT, VARCHAR(10), etc.).
Second, insert your values into the table:
INSERT INTO test (c1, c2) VALUES (r1, r2);
You should review the syntax and example for how to create a MySQL table.
There are 2 issues with your CREATE TABLE statement.
You need to specify the types of the columns, something like:
CREATE TABLE test (c1 INTEGER, c2 INTEGER);
You can't supply the values at the same time as create, but you can follow up with an insert statement:
INSERT INTO test (c1, c2) VALUES (1, 3),(2, 4);
The above gives a table with two rows, like this:
mysql> SELECT * FROM test;
+------+------+
| c1 | c2 |
+------+------+
| 1 | 3 |
| 2 | 4 |
+------+------+

SQL Syntax Sum and Count

I have a 1064 error:
You have an error in your SQL syntax; check the manual that correspond to your MySQL server version for the right syntax to use neear '*) as NB_FR, sum (*)) as MT_FR
FROM gc_mouvements where COOPX="477" or COOPX="4' at line 4
Here is the code I used, I don't understand the origin of the error:
ALTER TABLE gc_modele_retrait ADD COLUMN
(Nb_frais_477 int(5),Nb_frais_481 int(5),Mt_frais_477 int(5),Mt_frais_481 int(5));
UPDATE gc_modele_retrait
SET Nb_frais_477=0, Nb_frais_481=0, Mt_frais_477=0, Mt_frais_481=0;
DROP TABLE IF EXISTS gc_modele_retrait_frais;
CREATE TABLE gc_modele_retrait_frais
(PRIMARY KEY (COCO))
ENGINE=myisam
SELECT COCO, COOPX, COUNT(*) AS NB_FR, SUM(*) AS MT_OPE
FROM gc_mouvements WHERE COOPX="477" OR COOPX="481" GROUP BY COCO, COOPX;
The issue is with using SUM (*), you have to pass numerical value or column containing numerical value to SUM. In your case you need:
SUM (Nb_frais_477 + Nb_frais_481)

How to alter table to add a Range Partition

OK Guys, I understand your points... so let me put it this way,
Here is my table
CREATE TABLE TEST1
(
USERID integer,
ENTRYCREATEDDATE TIMESTAMP
) ;
And here is my alter query (I tried adding and removing ADD word below)
ALTER TABLE TEST1 PARTITION BY RANGE (USERID)
(
PARTITION P0 VALUES LESS THAN (10)
);
RESULT:
1. Error report:
SQL Error: ORA-01735: invalid ALTER TABLE option
01735. 00000 - "invalid ALTER TABLE option"
*Cause:
*Action:
Error report:
SQL Error: ORA-00902: invalid datatype
00000 - "invalid datatype"
*Cause:
*Action:
Now Please help me. Actually I want to partition on ENTRYCREATEDDATE, but will come to that later
Here's how to do it in Teradata:
http://www.info.teradata.com/HTMLPubs/DB_TTU_14_00/index.html#page/SQL_Reference/B035_1144_111A/Alter_Function-Syntax.020.106.html
MySQL:
https://dev.mysql.com/doc/refman/5.1/en/alter-table-partition-operations.html
Oracle:
https://docs.oracle.com/cd/E17952_01/refman-5.5-en/alter-table-partition-operations.html
Your google search skills need work sir!
Per your question: Make sure USERID is an INT