N1QL - Insert-Select - couchbase

I'm trying to execute an insert-select statement in N1QL (inserting documents that their key/value are the result of a select statement) and I'm failing to understand the syntax.
I tried executing:
insert into tempbucket (KEY payload.id,VALUE select * from default where payload.fooId in [100,101 ] ) RETURNING * ;
in some variations but nothing worked.
Edit: The SELECT statement is
select * from default where payload.fooId in [100,101 ]
The KEY of the documents I want to create is the value of the field key and the VALUE is the entire JSON of the SELECT statement mentioned above.

The KEY and VALUE must reference expressions from your query.
INSERT INTO tempbucket (KEY d.`key`, VALUE d)
SELECT d
FROM default d
WHERE payload.fooId IN [100,101 ]
;

Related

how to avoid values() with multiple values? [duplicate]

This is my python code which prints the sql query.
def generate_insert_statement(column_names, values_format, table_name, items, insert_template=INSERT_TEMPLATE, ):
return insert_template.format(
column_names=",".join(column_names),
values=",".join(
map(
lambda x: generate_raw_values(values_format, x),
items
)
),
table_name=table_name,
updates_on=create_updates_on_columns(column_names)
)
query = generate_insert_statement(table_name=property['table_name'],
column_names=property['column_names'],
values_format=property['values_format'], items=batch)
print(query) #here
execute_commit(query)
When printing the Mysql query my Django project shows following error in the terminal:
'VALUES function' is deprecated and will be removed in a future release. Please use an alias (INSERT INTO ... VALUES (...) AS alias) and replace VALUES(col) in the ON DUPLICATE KEY UPDATE clause with alias.col instead
Mysql doumentation does not say much about it.What does this mean and how to can i rectify it.
INSERT_TEMPLATE = "INSERT INTO {table_name} ({column_names}) VALUES {values} ON DUPLICATE KEY UPDATE {updates_on};"
Basically, mysql is looking toward removing a longstanding non-standard use of the values function to clear the way for some future work where the SQL standard allows using a VALUES keyword for something very different, and because how the VALUES function works in subqueries or not in a ON DUPLICATE KEY UPDATE clause can be surprising.
You need to add an alias to the VALUES clause and then use that alias instead of the non-standard VALUES function in the ON DUPLICATE KEY UPDATE clause, e.g. change
INSERT INTO foo (bar, baz) VALUES (1,2)
ON DUPLICATE KEY UPDATE baz=VALUES(baz)
to
INSERT INTO foo (bar, baz) VALUES (1,2) AS new_foo
ON DUPLICATE KEY UPDATE baz=new_foo.baz
(This only works on mysql 8+, not on older versions or in any version of mariadb through at least 10.8.3)
Note that this is no different if you are updating multiple rows:
INSERT INTO foo (bar, baz) VALUES (1,2),(3,4),(5,6) AS new_foo
ON DUPLICATE KEY UPDATE baz=new_foo.baz
From https://dev.mysql.com/worklog/task/?id=13325:
According to the SQL standard, VALUES is a table value constructor that returns a table. In MySQL this is true for simple INSERT and REPLACE statements, but MySQL also uses VALUES to refer to values in INSERT ... ON DUPLICATE KEY UPDATE statements. E.g.:
INSERT INTO t(a,b) VALUES (1, 2) ON DUPLICATE KEY
UPDATE a = VALUES (b) + 1;
VALUES (b) refers to the value for b in the table value constructor for the INSERT, in this case 2.
To make the value available in simple arithmetic expressions, it is part of the parser rule for simple_expr. Unfortunately, this also means that VALUES can be used in this way in a lot of other statements, e.g.:
SELECT a FROM t WHERE a=VALUES(a);
In all such statements, VALUES returns NULL, so the above query would not have the intended effect. The only meaningful usage of VALUES as a function, rather than a table value constructor, is in INSERT ... ON DUPLICATE KEY UPDATE. Also, the non-standard use in INSERT ... ON DUPLICATE KEY UPDATE does not extend to subqueries. E.g.:
INSERT INTO t1 VALUES(1,2) ON DUPLICATE KEY
UPDATE a=(SELECT a FROM t2 WHERE b=VALUES(b));
This does not do what the user expects. VALUES(b) will return NULL, even if it is in an INSERT .. ON DUPLICATE KEY UPDATE statement.
The non-standard syntax also makes it harder (impossible?) to implement standard behavior of VALUES as specified in feature F641 "Row and table constructors".

Getting value from array in a SELECT statement in Postgresql

I have created a table in postgresql with column as jsonb
CREATE TABLE IF NOT EXISTS my_table ( data jsonb );
And I have inserted the values inside jsonb
INSERT INTO my_table ("data") VALUES ('{"id":"100100","my_array":[{"createdTime":1629686783,"updatedTime":1632365183,"status":"Initiated","my_array_id":"12345678"},{"createdTime":1627008383,"updatedTime":1627008383,"status":"Completed","my_array_id":"789010111"}]}');
How can I get inserted value using select query in PostgreSQL. I have used the below , but it is returning empty results
select *
from my_table
where (not data->'my_array' ??| array[cast('{"12345678"}' as varchar[])])
Kindly help
I assume that you are trying to get all records from 'my_table' where my_array_id is different from a certain value. In this case 12345678.
In any case, you need to use the jsonb_array_elements function in order to access the particular item from the array, and after that arrow '->>' in order to access the particular attribute from that item(json).
This is the query for the aforementioned assumption.
with temp_CTE as
(
select m.*,jsonb_array_elements(m.data->'my_array')->>'my_array_id' as my_array_id from my_table m
)
select * from temp_CTE c
where c.my_array_id<>'12345678'

Insert date in table using json_populate_recordset

I'm trying insert data in table using this query
INSERT INTO table (
url,
v_count,
v_date)
SELECT
url,
v_count,
v_date FROM json_populate_recorset(null::record,
'[{"url_site":"test.com","visit_count":1,"visit_date":"2022-08-31"},
{"url_site":"dev.com","visit_count":2,"visit_date":"2022-08-31"}]'::json)
AS ("url" varchar(700), "v_count" integer, "v_date" date)
And I'm getting this error:
null value in column "v_date" of relation table violates not null constraint
Since my json could be hundreds of entries at some times,
how should I send the date in my json ?
There is another (efficient) way to insert this data in the table ?
Edit: in postico 1.5.20 my example above works as long as I have the json key named the same as the table columns, how can I reference differents names in my json keys?
Since v_date can resolve to null, you'll need to either skip them or provide a value when null appears.
To skip the null values, you may want to add a WHERE v_date NOTNULL clause to your SELECT statement.
Otherwise, you can use COALESCE() to assign a value when v_date is null. For example ... SELECT url, v_count, COALESCE(v_date,now()) FROM json_populate_recordset...

MySQL JSON_SET() to work with empty arrays

I have a table like this:
CREATE TABLE `test` (
`id` int(11) NOT NULL,
`settings` json NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO `test` (`id`, `settings`) VALUES
('1', '{\"foo\": {\"bar\": 1}}'),
('2', '{\"foobar\": 2}'),
('3', '[]');
I want to add a new setting to a row, so I tried JSON_SET:
SELECT *, JSON_SET(settings, '$.newFoo', 10) FROM test;
As you can see, it doesn't work on the item 3. The expected result is of course the same as on line 4; [] is the result of json-encoding an empty array in php, if that item doesn't have any setting.
Can make a single query that works for all the cases?
P.S.: What I need to do is an UPDATE, i.e. UPDATE test SET settings=JSON_SET(...) WHERE id=?;
This stumped me as well for quite awhile but try using JSON_ARRAY() instead of the double bracket notation '[]'. For example:
INSERT INTO `test` (`id`, `settings`) VALUES
('1', '{\"foo\": {\"bar\": 1}}'),
('2', '{\"foobar\": 2}'),
('3', JSON_ARRAY());
The reason your call to JSON_SET is not behaving as you expect is that the syntax you need to work with JSON arrays differs from what you need to work with individual JSON. Consider the following query, which adds a JSON to an empty array:
SELECT JSON_SET('[]', '$[0]', '{"newFoo": 10}') AS output;
This prints:
["{\"newFoo\": 10}"]
Demo
So the JSON_SET function appears to have two behaviors to it. When operating on JSON proper, it can either insert new keys or update keys which already exist. When operating on arrays, it can insert/update elements of the array, which might be entire JSON objects.
I solved by always storing the values as objects instead of arrays, in PHP you need to add a flag to the json_encode function:
json_encode($value, JSON_FORCE_OBJECT)
Or, as an alternative, make the field nullable and use COALESCE:
SELECT *, JSON_SET(COALESCE(settings, '{}'), '$.newFoo', 10) FROM test;
You can use CASE .. WHEN conditional operator to handle this in single query. Also, since your datatype for settings is Json, you will need to Cast() it to string (Char) first for checking []:
SELECT *,
CASE WHEN CAST(settings AS CHAR) = '[]'
THEN JSON_SET('{}', '$.newFoo', 10)
ELSE JSON_SET(settings, '$.newFoo', 10)
END AS modified_settings
FROM test;
Update query for the same would be as follows:
UPDATE test
SET settings = CASE WHEN CAST(settings AS CHAR) = '[]'
THEN JSON_SET('{}', '$.newFoo', 10)
ELSE JSON_SET(settings, '$.newFoo', 10)
END

Some problems with INSERT INTO statement

I have this mysql syntax:
INSERT INTO `utilizatori`(
utilizator
)
SELECT
'Mama'
FROM
`utilizatori`
WHERE
NOT EXISTS (SELECT `utilizator` FROM `utilizatori` WHERE utilizator='Mama')
utilizatori is a table, utilizator is a column, Mama is a value
This syntax will insert a value in table only if it doesnt exist.If the value exist it wont create it,so until now it works fine,but if there is no 'Mama' value,then it will insert it...the only problem is that it will insert it multiple times.For example if i have 4 rows,it will insert 'Mama' value 4 times,creating 4 rows.Any idea??
I would make the task easier, clearer by making utilizator field unique.
That way when you add new rows with existing value 'Mama' for utilizator in this case: mysql returns error with the code: 1062, and don't let user have multiple rows with Mama in the table.
So when you run query:
INSERT INTO `utilizatori` (utilizator) VALUES ('Mama')
You can check if MySQL returns any error, but better to check number of affected rows, if insert was successful it will be equal to 1 otherwise 0.
Checking mechanism depends what language and driver you use for connecting to database.
Since you had PHP tag selected you may be using PDO than
$statement->rowCount(); // $statement = PDOStatement, I assume you know this thing well
will give you desired result
Final simple example:
...
if ($statement->rowCount())
{
echo "Cool! You have been added to database";
}
else
{
echo "Hmms! Are you trying to duplicate something?";
}
Try to use group by :
INSERT INTO `utilizatori`(
utilizator
)
SELECT
'Mama'
FROM
`utilizatori`
WHERE
NOT EXISTS (SELECT `utilizator` FROM `utilizatori` WHERE utilizator='Mama')
group by utilizator
You are basically doing:
SELECT ... WHERE NOT EXISTS
...and inserting this in your table. As stated in the comments, just make your utilizator field unique and drop the whole SELECT part from your query.
Where Column is missing...
INSERT INTO `utilizatori`(
utilizator
)
SELECT
'Mama'
FROM
`utilizatori`
WHERE
'Mama'
NOT EXISTS (SELECT `utilizator` FROM `utilizatori` WHERE utilizator='Mama')