I am using Postgresql. My Yii2 code for the update is
ModelName::updateAll(['my_column' => "REPLACE(my_column1,'removed_','')"]);
Actual query is
update my_table set my_column = REPLACE(my_column1,'removed_','');
When I run my yii2 code it shows the error
SQLSTATE[22001]: String data, right truncated: 7 ERROR: value too long for type character varying(50)
The SQL being executed was: UPDATE "my_table" SET "my_column1"='REPLACE(my_column1,''removed_'','''')'
If you use ['column' => 'value'] syntax for attributes the framework expects that values of array are simple values and treats them accordingly. That's why your expression gets converted to string value instead of using as expression.
If you want to avoid that you need to wrap your values in yii\db\Expression like this:
ModelName::updateAll([
'my_column' => new \yii\db\Expression("REPLACE(my_column1,'removed_','')")
]);
Related
I have a PostgreSQL table called files which includes a jsonb table called formats. While some rows are [null], others have objects with this structure:
{
"thumbnail": {
"ext": ".jpg",
"url": "https://some-url.com/image01.jpg",
"name": "image01.jpg",
//...other properties
}
}
For every row I want to update the thumbnail.url and replace some-url with other-url.
I'm far from being an expert in PostgreSQL (or any other DB for that matter), and after some reading I tried to run the following query in pgAdmin:
UPDATE files
SET formats = jsonb_set(formats, '{thumbnail.url}', REPLACE('{thumbnail.url}', 'some-url', 'other-url'))
And I received this error: function jsonb_set(jsonb, unknown, text) does not exist
I tried to set format jsonb_set(formats::jsonb...), tried to target '{thumbnail}' instead of '{thumbnail.url}' - always the same error.
What am I doing wrong? Or is pgAdmin really doesn't support this function? How can I do such an update with pgAdmin query tool?
We can try to use ->> to get JSON content value of url and then replace your expect value from that.
Because your url field of your JSON might be string type we need to use " to content it before cast as JSONB
jsonb_set(target jsonb, path text[], new_value jsonb [, create_missing boolean])
UPDATE files
SET formats = jsonb_set(formats, '{thumbnail,url}', CONCAT('"',REPLACE(formats->'thumbnail'->>'url','some-url','other-url'),'"')::JSONB);
sqlfiddle
The second parameter of jsonb_set() must be an array with one array element for each "path" element. So the second parameter should be '{thumbnail,url}' or more obvious: array['thumbnail', 'url']
And the third parameter must be a jsonb value, but replace returns a text, so you need to use e.g. to_jsonb() to convert the result of the replace() to a jsonb value.
And as D-Shih pointed out, you need to extract the old value using ->>. But to get the URL you need to "navigate" to it: formats -> 'thumbnail ->> 'url'
I would also add a WHERE clause so that you only update rows that actually contain a URL.
UPDATE files
SET formats = jsonb_set(formats,
'{thumbnail,url}',
to_jsonb(replace(formats -> 'thumbnail' ->> 'url', 'some-url', 'other-url'))
)
where (formats -> 'thumbnail') ? 'url'
How can I concatenate a string inside of a concatenated jsonb object in postgresql? In other words, I am using the JSONb concatenate operator as well as the text concatenate operator in the same query and running into trouble.
Or... if there is a totally different query I should be executing, I'd appreciate hearing suggestions. The goal is to update a row containing a jsonb column. We don't want to overwrite existing key value pairs in the jsonb column that are not provided in the query and we also want to update multiple rows at once.
My query:
update contacts as c set data = data || '{"geomatch": "MATCH","latitude":'||v.latitude||'}'
from (values (16247746,40.814140),
(16247747,20.900840),
(16247748,20.890570)) as v(contact_id,latitude) where c.contact_id = v.contact_id
The Error:
ERROR: invalid input syntax for type json
LINE 85: update contacts as c set data = data || '{"geomatch": "MATCH...
^
DETAIL: The input string ended unexpectedly.
CONTEXT: JSON data, line 1: {"geomatch": "MATCH","latitude":
SQL state: 22P02
Character: 4573
You might be looking for
SET data = data || ('{"geomatch": "MATCH","latitude":'||v.latitude||'}')::jsonb
-- ^^ jsonb ^^ text ^^ text
but that's not how one should build JSON objects - that v.latitude might not be a valid JSON literal, or even contain some injection like "", "otherKey": "oops". (Admittedly, in your example you control the values, and they're numbers so it might be fine, but it's still a bad practice). Instead, use jsonb_build_object:
SET data = data || jsonb_build_object('geomatch', 'MATCH', 'latitude', v.latitude)
There are two problems. The first is operator precedence preventing your concatenation of a jsonb object to what is read a text object. The second is that the concatenation of text pieces requires a cast to jsonb.
This should work:
update contacts as c
set data = data || ('{"geomatch": "MATCH","latitude":'||v.latitude||'}')::jsonb
from (values (16247746,40.814140),
(16247747,20.900840),
(16247748,20.890570)) as v(contact_id,latitude)
where c.contact_id = v.contact_id
;
I'm using python 3.8 and psycopg2
I'm trying to insert a registry in the database.
I have a function that formats a query and send as result a list with 2 values, one is the query and the other the values.
I made a test and put a fixed value with the exact value of the result list query[1] and worked without error, but when I use the query[1] as values instead the value by itself I got this error:
TypeError: not all arguments converted during string formatting
At my log I have these values for the query list, result of my query construction function.
['INSERT INTO country (code, name, flag, update_time) VALUES(%s,%s,%s,%s)', "('US', 'USA', 'https://example.com/flags/us.svg', 1596551810)"]
query[0]
INSERT INTO country (code, name, flag, update_time) VALUES(%s,%s,%s,%s)
query[1]
('US', 'USA', 'https://example.com/flags/us.svg', 1596551810)
This is the code snipet
`
cursor = connection.cursor()
query_insert = query[0]
query_values = tuple(query[1])
cursor.execute(query_insert,(query_values))
I tried to put it as tuple, use parentheses, but error persists.
If I put the value of the query[1] at my code,as values, work well, so I suppose that the error is at the values part of the cursor.execute parameters.
Any help is welcome !
I'm trying to update a row in my PostgreSQL database and it's saying it's not finding the x column. the thing is the column pg is trying to find is actually a parameter for the new value in the jsonb_set function, so I'm at my wits end.
It's hard to explain, so I included the query and the error it throws.
Tried adding quotes, double-quotes, brackets, inside and out... didn't work.
UPDATE public.sometable
SET somecolumn = jsonb_set(somecolumn, '{firstKey, secondKey}', someInputString), update_date=NOW(), update_username="someone#somewhere.com"
WHERE id=1
RETURNING *
I'm expecting the value of the row I'm updating to be returned, instead I get:
ERROR: column "someInputString" does not exist
LINE 1: ...n = jsonb_set(somecolumn , '{firstKey, secondKey}', someInputString)...
You have to deliver a valid json value as the third argument of the function:
UPDATE public.sometable
SET
somecolumn = jsonb_set(somecolumn, '{firstKey, secondKey}', '"someInputString"'),
update_date = now(),
update_username = 'someone#somewhere.com'
WHERE id = 1
RETURNING *
Note, I guess update_username is a text, so you should use single quotes for a simple text.
Db<>fiddle.
I'm using PostgreSQL 9.3.
I have a varchar column in a table that can be null and I want to update it depending of its value is null or not.
I didn't manage to do a function that takes a String as argument and updates the value like this:
If the column is null, the function concatenates the current string value, a comma and the string given as argument, else it just adds the string at the end of the current string value (without comma).
So how can I make a different Update depending of the column value to update?
You can use a case statement to conditionally update a column:
update the_table
set the_colum = case
when the column is null then 'foobar'
else the_column||', '||'foobar'
end
An another approach
UPDATE foo
SET bar = COALESCE(NULLIF(concat_ws(', ', NULLIF(bar, ''), NULLIF('a_string', '')), ''), 'a_string')