PostgreSQL type cast not working when using with UPDATE statement - sql

I have a column address in students table which actually stores a JSON object but it is of type text for legacy reasons. Now, to get the value of any of these keys in the json object, I use postgres type cast :: operator with json -> operator as shown
select address::jsonb->'pincode' from students where id='xyz';
This query returns the correct pincode for the student with id xyz. Now lets say, I want to update the pincode for a student, and now, if I do something like
update students set address::jsonb->'pincode'='182741' where id='abc';
I get this error
ERROR: syntax error at or near "::"
I know I can overwrite the entire column value but that is a lot to do if you just want to update one key. Can anyone help me understand why we cannot use the type cast operator here? Any what is the correct way to update only one key in the JSON object?

Use jsonb_set from here JSON functions.
create table students (id integer, address varchar);
insert into students values (1, '{"name": "Adrian", "pincode": 1234}');
select address::jsonb->'pincode' from students where id=1;
1234
update students set address = jsonb_set(address::jsonb, '{pincode}', '182741') where id =1;
select * from students;
id | address
----+---------------------------------------
1 | {"name": "Adrian", "pincode": 182741}

Related

Invalid token error when using jsonb_insert in postgresql

As a little bit of background. I want to fill a column with jsonb values using values from other columns. Initially, I used this query:
UPDATE myTable
SET column_name =
row_to_json(rowset)
FROM (SELECT column1, column2 FROM myTable)rowset
However, this query seems to run for way too long (a few hours before I stopped it) on a dataset with 9 million records. So I looking for a solution with the second FROM clause and found the jsonb_insert function. To test the query I first ran this sample query:
SELECT jsonb_insert('{}','{column1}','500000')
Which gives {'column1':500000} as output. Perfect, so I tried to fill the value using the actual column:
SELECT jsonb_insert('{}':,'{column1}',column1) FROM myTable WHERE id = <test_id>
This gives a syntax error and a suggestion to add argument types, which leads me to the following:
SELECT jsonb_insert('{}':,'{column1}','column1')
FROM myTable WHERE id = <test_id>
SELECT jsonb_insert('{}'::jsonb,'{column1}'::jsonb,column1::numeric(8,0))
FROM myTable WHERE id = <test_id>
Both these queries give invalid input type syntax error, with Token 'column1' is invalid.
I really can not seem to find the correct syntax for these queries using documentation. Does anyone know what the correct syntax would be?
Because jsonb_insert function might need to use jsonb type for the new_value parameter
jsonb_insert(target jsonb, path text[], new_value jsonb [, insert_after boolean])
if we want to get number type of JSON, we can try to cast the column as string type before cast jsonb
if we want to get a string type of JSON, we can try to use concat function with double-quotes sign.
CREATE TABLE myTable (column1 varchar(50),column2 int);
INSERT INTO myTable VALUES('column1',50000);
SELECT jsonb_insert('{}','{column1}',concat('"',column1,'"')::jsonb) as JsonStringType,
jsonb_insert('{}','{column2}',coalesce(column2::TEXT,'null')::jsonb) as JsonNumberType
FROM myTable
sqlfiddle
Note
if our column value might be null we can try to put 'null' for coalesce function as coalesce(column2::TEXT,'null').

Where to use table types and where structures?

Why we use Table Type in SAP/ABAP? We can declare as type of table as shown below.
DATA it_doc TYPE TABLE OF table_name.
And if I want to store for specific attribute of table, I can use structure type.
TYPES: BEGIN OF st_student,
sid TYPE i,
sname TYPE c LENGTH 8,
END OF st_student.
DATA student TYPE st_student.
Is there any performance difference between table type and structure?
If I understand you correctly, you are talking about table types in the data dictionary. Since you can use the statement TYPE TABLE OF <structure> it might seem unintuitive to create a table type on top of that. However you need this table type if you want to pass a whole table as an argument to a Function Module or Class Method.
For example, you cannot write the following:
methods PASS_TABLE
returning
value(rt_table) TYPE TABLE OF <structure> .
In this case you have to use a dictionary table type:
methods PASS_TABLE
returning
value(rt_table) TYPE dict_table_type .
No, tables and structures are actually very different, so your concerns about performance are a bit unnecessary. As I stated in my comment, a table is a list of elements.
Example
You want to store information about a school class. Your application should be able to store data like name, birthdate, gender etc. of one student. To group those fields together, one would use a structure:
TYPES:
BEGIN OF student,
name TYPE string,
birth TYPE d,
gender TYPE char1,
END OF student.
Now you can declare a variable of type student and assign data like that:
DATA stud1 TYPE student.
stud1-name = 'Joe'.
...
You now want to put students together in a classroom. You'll need an internal table for this.
TYPES classroom TYPE STANDARD TABLE OF student WITH EMPTY KEY.
" ignore STANDARD and WITH EMPTY KEY for now
DATA e3fi TYPE classroom.
" fill table here
DATA joe TYPE student.
" init joe
APPEND joe TO e3fi.
DATA susan TYPE student.
" init susan
APPEND susan TO e3fi
After that your classroom e3fi contains two students susan and joe. Each of these students has individual name, birthdate and so on.

How to select from User Defined Table Type?

Select * from sys.table_types where user_type_id = TYPE_ID(N'dbo.udt_test');
The above query returns me data but when I try to query the data within, it says dbo.udt_test not exists?
Select * from dbo.udt_test
https://msdn.microsoft.com/en-us/library/ms131086.aspx
Referred to the above link, there should be no problem with the select query to display data. May I know if I missing something obvious here?
Because dbo.udt_test is a Table Type, not a Table instance.
The link in your question shows how a User Defined Type is defined and is used as data type for column.
you seem to have created a new table type.
You can create table variable of type dbo.udt_test and use that table to insert/update/delete/select data from it.
In the link, you have this code..
INSERT INTO dbo.Points (PointValue) VALUES (CONVERT(Point, '3,4'));
'Point' is a type here. You cannot do select Point from Sometable same as in the case of Select VARCHAR from Sometable
In the same way, you cannot have SELECT * FROM TABLETYPE

column doesn't exist in table whiel its showing the column in schema

i am using postgresql .i am using psql.i run a command \d+ user i get schema of user table .
but when i run the command select first_name from user .its giving me error
ritesh=# select first_name from user;
ERROR: column "first_name" does not exist
LINE 1: select first_name from user;
^
as you can see in the screenshot .How to resolve it and where i am mistaking please explain.
This problem occurs because "user" is a keyword. You should not use it for table names, etc. Otherwise you get fun like this.
See, user is a magic pseudo-function that returns the current username - it's an alias for current_user:
regress=> SELECT user;
current_user
--------------
testuser
(1 row)
So what you're trying to do is call the function user in a set-returning context, and get the column first_name from it. The function result has no such column, hence the error.
Don't just schema-qualify your table as public.user to get around this. At minimum you should be using quoted identifiers if you're going to use SQL keywords for table names, e.g.:
select first_name from "user";
but really, it'll be much better to just name your table something that doesn't conflict with a keyword.
try "select first_name from public.user"

passing an array into oracle sql and using the array

I am running into the following problem, I am passing an array of string into Oracle SQL, and I would like to retrieve all the data where its id is in the list ...
here's what i've tried ...
OPEN O_default_values FOR
SELECT ID AS "Header",
VALUE AS "DisplayValue",
VALUE_DESC AS "DisplayText"
FROM TBL_VALUES
WHERE ID IN I_id;
I_id is an array described as follows - TYPE gl_id IS TABLE OF VARCHAR2(15) INDEX BY PLS_INTEGER;
I've been getting the "expression is of wrong type" error.
The I_id array can sometimes be as large as 600 records.
My question is, is there a way to do what i just describe, or do i need to create some sort of cursor and loop through the array?
What has been tried - creating the SQL string dynamically and then con-cat the values to the end of the SQL string and then execute it. This will work for small amount of data and the size of the string is static, which will caused some other errors (like index out of range).
have a look at this link: http://asktom.oracle.com/pls/asktom/f?p=100:11:620533477655526::::P11_QUESTION_ID:139812348065
effectively what you want is a variable in-list with bind variables.
do note this:
"the" is deprecated. no need for it
today.
TABLE is it's replacement
select * from TABLE( function );
since you already have the type, all you need to do is something similar to below:
OPEN O_default_values FOR
SELECT ID AS "Header",
VALUE AS "DisplayValue",
VALUE_DESC AS "DisplayText"
FROM TBL_VALUES
WHERE ID IN (select column_value form table(I_id));