Can I Search for a Specific Row and Update it?? Google BigQuery Question - sql

I am new to BigQuery and was wondering if there was a way to search for a specific row, then individually update its columns using a Query. I am very new to database and SQL, and would love some of your help.

Yes you can. Typically this is achieved through data manipulation language (DML). For this specific example you would want use an UPDATE statement.
Documentation on this can be found here:
https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#update_statement
As a word of caution verify your where clause before you execute to ensure you are targeting the correct rows.
For example:
UPDATE your_table
SET assigned_to_user = 'updated_value' -- the value you want to update to
WHERE -- this is where you define your criteria to narrow down to a subset of rows
criteria_column = 'target_values' -- this is your critera
-- and criteria_column_2 = 'other_value' -- if you need to expand more critiera just use logic operators like `and` or `or`
You can also test out what will be updated by issuing a select statement with the same criteria as your update and seeing which columns come back, for example:
select *
from your_table
WHERE
criteria_column = 'target_values'

Related

SQL update multiple rows with different values where they match a value from a list

So perhaps the title is a little confusing. If you can suggest better wording for that please let me know and i'll update.
Here's the issue. I've got a table with many thousands of rows and i need to update a few thousand of those many to store latest email data.
For example:
OldEmail#1.com => NewEmail#1.com
OldEmail#2.com => NewEmail#2.com
I've got a list of old emails ('OldEmail#1.com','OldEmail#2.com') and a list of the new ('NewEmail#1.com','NewEmail#2.com'). The HOPE was was to sort of do it simply with something like
UPDATE Table
SET Email = ('NewEmail#1.com','NewEmail#2.com')
WHERE Email = ('OldEmail#1.com','OldEmail#2.com')
I hope that makes sense. Any questions just ask. Thanks!
You could use a case expression:
update mytable
set email = case email
when 'OldEmail#1.com' then 'NewEmail#1.com'
when 'OldEmail#2.com' then 'NewEmail#2.com'
end
where email in ('OldEmail#1.com','OldEmail#2.com')
Or better yet, if you have a large list of values, you might create a table to store them (like myref(old_email, new_email)) and join it in your update query, like so:
update t
set t.email = r.new_email
from mytable t
inner join myref r on r.old_email = t.email
The actual syntax for update/join does vary accross databases - the above SQL Server syntax.
With accuracy to the syntax in particular DBMS:
WITH cte AS (SELECT 'NewEmail#1.com' newvalue, 'OldEmail#1.com' oldvalue
UNION ALL
SELECT 'NewEmail#2.com', 'OldEmail#2.com')
UPDATE table
SET table.email = cte.newvalue
FROM cte
WHERE table.email = cte.oldvalue
or, if CTE is not available,
UPDATE table
SET table.email = cte.newvalue
FROM (SELECT 'NewEmail#1.com' newvalue, 'OldEmail#1.com' oldvalue
UNION ALL
SELECT 'NewEmail#2.com', 'OldEmail#2.com') cte
WHERE table.email = cte.oldvalue
Consider prepared statement for rows update in large batches.
Basically it works as following :
database complies a query pattern you provide the first time, keep the compiled result for current connection (depends on implementation).
then you updates all the rows, by sending shortened label of the prepared function with different parameters in SQL syntax, instead of sending entire UPDATE statement several times for several updates
the database parse the shortened label of the prepared function , which is linked to the pre-compiled result, then perform the updates.
next time when you perform row updates, the database may still use the pre-compiled result and quickly complete the operations (so the first step above can be skipped).
Here is PostgreSQL example of prepare statement, many of SQL databases (e.g. MariaDB,MySQL, Oracle) also support it.

Why do I need the 'match' part of a SQL merge, in this scenario?

Consider the following:
merge into T t1
using (select ID,Col1 from T where ID = 123) t2
on 1 = 0
when not matched then insert (Col1) values (t2.Col1);
Cominig from a programming background, to me this translates to:
"Evaluate false (i.e. 1 = 0), and when it is false (i.e. all the time), insert."
Is it not possible to just omit the match condition?
Is it because of my select's where condition that I'm confused here? Should this condition be moved to the on?
NOTE:
Due to restrictions with output, I cannot use insert. I need to output the results of this merge into a temporary table for reasons outside of the scope of what I'm asking.
In the answer you've linked to in the comments, as I've hopefully made clear, we are abusing the MERGE statement.
The query you've shown here could trivially be replaced by:
insert into T(Col1) select Col1 from T where ID = 123
However, if you want to be able to add an OUTPUT clause, and that OUTPUT clause needs to reference both the newly inserted data and data from the source table, you're not allowed to write such a clause on an INSERT statement.
So, we instead use a MERGE statement, but not for its intended purpose. The entire purpose is to force it to perform an INSERT and write our OUTPUT clause.
If we examine the documentation for MERGE, we see that the only clause in which we can specify to perform an INSERT is in the WHEN NOT MATCHED [BY TARGET] clause - in both the WHEN MATCHED and WHEN NOT MATCHED BY SOURCE clauses, our only options are to UPDATE or DELETE.
So, we have to write the MERGE such that matching always fails - and the simplest way to do that is to say that matching should occur when 1 = 01 - which, hopefully, is never.
1Since SQL Server doesn't support boolean literals

Update from aggregate in same table if aggregate value wrong - SQL Server/Oracle/Firebird

I have a table with grouped tasks:
tt_plan_task_id is the id
records with tt_plantype=1 represent 'groups'
tasks in/under a group have a tt_group_id pointing to the tt_plan_task_id
there are tasks that don't belong to a group (tt_group_id is null)
groups nest multiple levels
I need to fix (update) the tt_fromdate field values for the group records if they do not match the min(tt_fromdate) from the underlying tasks (they always have a value).
To fix them all I could do
update tt_plan_task g
set tt_fromdate=
(select min(t.tt_fromdate) from tt_plan_task t
where (t.tt_group_id=g.tt_plan_task_id))
where (g.tt_plantype=1)
This statement avoids the UPDATE FROM syntax that I see in many (SQL server) answers - Firebird does not support that.
There are 2 complications
I want to do the update only if g.tt_fromdate <> min(t.tt_fromdate), so I would have to add a reference to min(tt_fromdate) to the outer where.
I tried using an alias for the aggregate and referencing that but that got me nowhere (syntax errors)
SQL Server does not like the table alias in the update, but solutions like these use the UPDATE FROM syntax again ;-( How do I work around that then?
How do I tie 1. and 2. into my update statement so that it works?
As noted in the title, this needs to execute in SQL Server, Oracle, and Firebird
Note: Since groups can contain groups, the update should ideally be executed 'from the bottom up', i.e. deepest groups first.
But since this is just a rough correction for a corrupt database, doing one 'lineair' pass over all groups is good enough.
To get around SQL Server's non-standard way for update table aliases, simply don't use any.
As to using the aggregate result in both the SET clause and the WHERE clause, I suppose the only way all DBMS work with, is to write the aggregation query twice.
update tt_plan_task
set tt_fromdate =
(
select min(t.tt_fromdate)
from tt_plan_task t
where t.tt_group_id = tt_plan_task.tt_plan_task_id
)
where (tt_plantype=1)
and
(
tt_fromdate <>
(
select min(t.tt_fromdate)
from tt_plan_task t
where t.tt_group_id = tt_plan_task.tt_plan_task_id
)
);

Update table in run time and the column not known in compile time

I am trying to write the SQL to update multiple columns based on some code condition to the table in the code.
For example, make it the easiest one in two columns
UPDATE table set A = valueA where conditionA..
OR UPDATE table set B=valueB where conditionA..
OR UPDATE table set A=valueA, B=valueB where conditionA..
The condition is the same, but valueA/valueB may not exist depending on the code
Is there any convenient way to combine them together in one SQL such as the select one WHERE 1=1 and <condition> so that I can add the conditions regardless one or more than one conditions?
Hope it make sense.
if you use the same condition you can write the query simply like this:
UPDATE [table] SET A = valueA, B=valueB, C=valueC WHERE <condition>
But if you need different conditions for all the fields, you could you a CASE operator like this:
UPDATE [table] SET A = CASE WHEN <cond_for_A> THEN valA ELSE A END,
CASE WHEN <cond_for_B> THEN valB ELSE B END,
CASE WHEN <cond_for_C> THEN valC ELSE C END
You vary the fields being updated, presumably based on some condition in your code, which probably means you won't be able to get away with just one SQL statement - bound parameters cannot "add" or "remove" columns within SQL text.
If you have a small number of columns, you can make a separate SQL statement for each combination of them that is of interest. Otherwise, you'll likely need to construct the SQL text dynamically and fill the SET clause of your statement so it includes exactly the columns you need.
None of this should serve as an excuse to skip properly binding all parameters, though!

Update A multi-valued field in Access

I have created a lookup table in Access to provide the possible values for a column. Now I need to update this column with the data it had before I converted the column. I am unable to figure out a SQL Query that will work. I keep getting the error "An UPDATE or DELETE query cannot contain a multi-valued field." My research has suggested that I just need to set the value of the column but this always updates 0 records:
UPDATE [table_name] SET [column_name].Value = 55 WHERE [table_name].ID = 16;
I know this query will work if I change it to update a text column, so it is definitely a problem with just this column.
If you're adding a value to your multi-valued field, use an append query.
INSERT INTO table_name( [column_name].Value )
VALUES (55)
WHERE ID = 16;
If you want to change one particular value which exists in your multi-valued field, use an UPDATE statement. For example, to change the 55 to 56 ...
UPDATE [table_name]
SET [column_name].Value = 56
WHERE [column_name].Value = 55 And ID = 16;
See Using multivalued fields in queries for more information.
I have figured this out! It certainly was counter-intuitive! You have to use an INSERT statement to do the update.
-- Update a record with a multi-valued field that has no value
INSERT INTO [table_name] ( [[column_name].[Value] )
VALUES(55)
WHERE [table_name].ID = 16;
This confused me because I was expecting an UPDATE statement. I think it actually inserts a record into a hidden table that is used to associate multiple values with this column.
I am working with Sharepoint, I created the tables as multi-value fields, ran into the error with my INSERT INTO statement, went back to Sharepoint to change to non-multi-value fields, but that didn't fix it.
Recreated the table without using multi-value fields, and the INSERT INTO worked just fine.
do not use the .value part
UPDATE [table_name] SET [column_name] = 55 WHERE [table_name].ID = 16;
INSERT INTO Quals (cTypes.[value])
SELECT Quals_ContractTypes.ContractType
FROM Quals_ContractTypes
WHERE (Quals.ID = Quals_ContractTypes.ID_Quals);
I gotta say I didn't understand very well your problem but I saw something strange in your query. Try this:
UPDATE [table_name] SET [column_name]= 55 WHERE [table_name].ID = 16;
UPDATE:
Look at this link: it has an example
UPDATE Issues
SET Issues.AssignedTo.Value = 10
WHERE (((Issues.AssignedTo.Value)=6)
AND ((Issues.ID)=8));
NOTES
You should always include a WHERE
clause that identifies only the
records that you want to update.
Otherwise, you will update records
that you did not intend to change. An
Update query that does not contain a
WHERE clause changes every row in the
table. You can specify one value to
change.
The Multi-Valued field refers to Access databases that have tables with columns, that allow you to select multiple values, like a Combo Checkbox list.
THOSE are the only Access types that SQL cannot work with. I've tested all Access lookup possibilities, including hard-coded values, and lookup tables. They work fine, but if you have a column that has the Allow Multiple select options, you're out of luck. Even using the INSERT INTO as mentioned below, will not work as you'll get a similar but different error, about INSERTing into multi-valued fields.
As mentioned it's best to avoid using such tables outside of Access, and refer to a table specifically for your external needs. Then write a macro/vba script to update the real tables with the data from the "auxiliary" table.