TSQL bulk update with select subquery - tsql

I'm more familiar with Oracle so the syntax of SQL Server 2008 is throwing me. I'm trying to perform an update of multiple rows with a query equivalent to
update Table
set type = 'typeA'
where id in
(select id from Table where type='typeB')
I am receiving the following error:
Msg 512, Level 16, State 1, Procedure Assigned_To_Email, Line 19
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Searching for a TSQL specific solution I tried the following syntax but received the same error.
update a
set type = 'typeA'
from Table a
join Table b
on a.id = b.id
where b.type='typeB'
I've read that an update with the subquery should work, but it's not been my experience. Is there something more basic missing here?
Thanks for any help!

Your update statement does not have to use a sub-query or a join.
update Table
set type = 'typeA'
where type = 'typeB'

Related

PyCharm has outdated SQL dialects?

I'm working with PostgresQL database with a python script. I have a query like this:
UPDATE orders SET id=%s, client=%s, contents=%s, adress=%s, detail=%s, price=%s HAVING MIN(id)
It works fine, but PyCharm says that "having" statement doesn't exist and i should use "where" (while "where" gives an exception in this query because I'm using "MIN"). And I have SQL dialect in PyCharm set to "PostgresQL". Any ways to fix this annoying issue?
UPD: my bad, this query isn't working. It somehow didn't throw an exception in python, but the row in database wasn't updated. Then what query should I use to update row with the least id?
You can get min(id) in the same query with either a sub-query or a CTE. Perhaps something like:
update some_tbl
set col = 1
where id = (select min(id)
from some_tbl
) ;
OR
with lowers(mid) as
(select min(id)
from some_tbl
)
update some_tbl st
set col = 1
from lowers l
where st.id = l.mid;

Update from existing table in Redshift

I would like to update a value in Redshift table from results of other table, I'm trying to run to following query but received an error.
update section_translate
set word=t.section_type
from (
select distinct section_type from mr_usage where section_type like '%sディスコ')t
where word = '80sディスコ'
The error I received:
ERROR: Target table must be part of an equijoin predicate
Can't understand what is incorrect in my query.
You need to make the uncorrelated subquery to a correlated subquery,
update section_translate
set word=t.section_type
from (
select distinct section_type,'80sディスコ' as word from mr_usage where section_type like '%sディスコ')t
where section_translate.word = t.word
Otherwise, each record of the outer query is eligible for updates and the query engine rejects it. The way Postgre (and thus Redshift) evaluates uncorrelated subqueries is slightly different from SQL Server/ Oracle etc.

DB2 Query Structure Using User-Defined Function as a Table

I'm a little new to DB2, and am having trouble developing a query. I have created a user-defined function that returns a table of data which I want to then join and select from in larger select statement. I'm working on a sensitive db, so the query below isn't what I'm literally running, but it's almost exactly like it (without the other 10 joins I have to do lol).
select
A.customerId,
A.firstname,
A.lastname,
B.orderId,
B.orderDate,
F.currentLocationDate,
F.currentLocation
from
customer A
INNER JOIN order B
on A.customerId = B.customerId
INNER JOIN table(getShippingHistory(B.customerId)) as F
on B.orderId = F.orderId
where B.orderId = 35
This works great if I run this query without the where clause (or some other where clause that doesn't check for an ID). When I include the where clause, I get the following error:
Error during Prepare 58004(-901)[IBM][CLI Driver][DB2/LINUXX8664]
SQL0901N The SQL statement failed because of a non-severe system
error. Subsequent SQL statements can be processed. (Reason "Bad Plan;
Unresolved QNC found".) SQLSTATE=58004
I have tracked the issue down to fact that I'm using one of join criteria for the parameters (B.customerId). I have validated this fact by replacing B.customerId with a valid customerId, and the query works great. Problem is, I don't know the customerId when calling this query. I know only the orderId (in this example).
Any thoughts on how to restructure this so I can make only 1 call to get all the info? I know the plan is the problem b/c the customerId isn't getting resolved before the function is called.
So if I understand correctly, the function getShippingHistory(customerId) returns a table.
And if you call it with a single customer Id that table gets joined in your query above no problem at all.
But the way you have the query written above, you are asking db2 to call the function for every row returned by your query (i.e. every b.customerId that matches your join and where conditions).
So I'm not sure what behaviour you are expecting, because what you're asking for is a table back for every row in your query, and db2 (nor I) can figure out what the result is supposed to look like.
So in terms of restructuring your query, think about how you can change the getShippingHistory logic when multiple customer Ids are involved.
i found the best solution (given the current query structure) is to use a LEFT join instead of an INNER join in order force the LEFT part of the join to happen which will resolve the customerId to a value by the time it gets to the function call.
select
A.customerId,
A.firstname,
A.lastname,
B.orderId,
B.orderDate,
F.currentLocationDate,
F.currentLocation
from
customer A
INNER JOIN order B
on A.customerId = B.customerId
LEFT JOIN table(getShippingHistory(B.customerId)) as F
on B.orderId = F.orderId
where B.orderId = 35

I want to update multiple rows in a table but iff the value of a certain column does not exist in a different table?

This select query give me the columns I want to modify
Select * From Location
where Location.DeviceAddress not in (Select DeviceAddress From Device) order by DeviceAddress desc
However, this update query
Update Location
set DeviceAddress = NULL
where Location.DeviceAddress not in (Select DeviceAddress From Device)
Gives me the following error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated.
For reference I am using Microsoft Server 2008 , and, as always, assistance is much appreciated
Turns out this error was being caused by a query in an update trigger on the Location table so I was able to solve it by disabling (and after some time fixing) the trigger. Thank you to all who took the time to help me.
you might want to try
Update Location set DeviceAddress = NULL where Location.DeviceAddress not in (Select
top 1 DeviceAddress From Device where Device.DeviceAddress == Location.DeviceAddress)
in this case your subquery will return only 1 value instead of multiple.
try
Update
Location
set
DeviceAddress = NULL
where
not exists (Select null From Device where Device.DeviceAddress = Location.DeviceAddress)

HAVING clause in PostgreSQL

I'm rewriting the MySQL queries to PostgreSQL. I have table with articles and another table with categories. I need to select all categories, which has at least 1 article:
SELECT c.*,(
SELECT COUNT(*)
FROM articles a
WHERE a."active"=TRUE AND a."category_id"=c."id") "count_articles"
FROM articles_categories c
HAVING (
SELECT COUNT(*)
FROM articles a
WHERE a."active"=TRUE AND a."category_id"=c."id" ) > 0
I don't know why, but this query is causing an error:
ERROR: column "c.id" must appear in the GROUP BY clause or be used in an aggregate function at character 8
The HAVING clause is a bit tricky to understand. I'm not sure about how MySQL interprets it. But the Postgres documentation can be found here:
http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-HAVING
It essentially says:
The presence of HAVING turns a query
into a grouped query even if there is
no GROUP BY clause. This is the same
as what happens when the query
contains aggregate functions but no
GROUP BY clause. All the selected rows
are considered to form a single group,
and the SELECT list and HAVING clause
can only reference table columns from
within aggregate functions. Such a
query will emit a single row if the
HAVING condition is true, zero rows if
it is not true.
The same is also explained in this blog post, which shows how HAVING without GROUP BY implicitly implies a SQL:1999 standard "grand total", i.e. a GROUP BY ( ) clause (which isn't supported in PostgreSQL)
Since you don't seem to want a single row, the HAVING clause might not be the best choice.
Considering your actual query and your requirement, just rewrite the whole thing and JOIN articles_categories to articles:
SELECT DISTINCT c.*
FROM articles_categories c
JOIN articles a
ON a.active = TRUE
AND a.category_id = c.id
alternative:
SELECT *
FROM articles_categories c
WHERE EXISTS (SELECT 1
FROM articles a
WHERE a.active = TRUE
AND a.category_id = c.id)
SELECT * FROM categories c
WHERE
EXISTS (SELECT 1 FROM article a WHERE c.id = a.category_id);
should be fine... perhaps simpler ;)