I want to add a condition in update I am really not sure how to do it.
I want to do following:
UPDATE
xyz_table
SET
cap = some_text, IF (some_text IS NULL) THEN some_text = alternate_text ENDIF
WHERE
alternate_text <> '' AND
cap IS NULL AND
some_relation_id IN ( 50, 51, 52 );
If there is really any way to do this, please suggest else I think I will need to execute same query twice to achieve this.
Thanks in Advance :)
You can use case or coalesce(). This is the set statement:
SET cap = some_text,
some_text = COALESCE(some_text, alternate_text)
that should do:
UPDATE
xyz_table
SET
cap = some_text, some_text = (case when some_text IS NULL THEN alternate_text else some_text end)
WHERE
alternate_text <> '' AND
cap IS NULL AND
some_relation_id IN ( 50, 51, 52 );
dont forget to BEGIN transaction before running
In your particular example, the simplest way would be using IsNull().
UPDATE
xyz_table
SET cap = ISNULL(some_text, alternate_text)
WHERE alternate_text <> '' AND
cap IS NULL AND
some_relation_id IN ( 50, 51, 52 );
for other conditions, I tend to use a case statement.
UPDATE
xyz_table
SET cap = CASE WHEN some_text = '' THEN alternate_text ELSE some_text END
WHERE alternate_text <> '' AND
cap IS NULL AND
some_relation_id IN ( 50, 51, 52 );
Related
Hey I have this query
IF (select kmkood from or_arved_read where kmkood = '1' or kmkood = '14' or kmkood = '15' or kmkood = '6' )
BEGIN
SET #stat_vat = 21
IF (select kmkood from or_arved_read where kmkood = '2' or kmkood = '7' )
SET #stat_vat = 12
But it returns An expression of non-boolean type specified in a context where a condition is expected, near 'BEGIN'.
how can i fix it?
Firstly, your IF doesn't have a boolean expression. The subquery returns a value (or more accurately for this scenario will return many and cause a different error) for the column kmkood, but then you don't do anything with that value. What value does that column need? The format should be something like this:
IF (SELECT SomeColumn FROM dbo.SomeTable WHERE... ) = 'SomeValue'
Also, if you have a BEGIN you need an END afterwards, which you don't have:
IF (SELECT SomeColumn FROM dbo.SomeTable WHERE... ) = 'SomeValue'
BEGIN
{Do several statements}
END
As, however, you are just doing a SET statement then you don't actually need the BEGIN and END statements.
I suspect what you are really after here, however, in an EXISTS:
IF EXISTS(SELECT 1 FROM dbo.or_arved_read WHERE kmkood IN (1,14,15,6))
SET #stat_vat = 21;
IF EXISTS(SELECT 1 FROM dbo.or_arved_read WHERE kmkood IN (2,7))
SET #stat_vat = 12;
You don't need all those ORs either, an IN works fine, and numbers shouldn't be in single quotes, so that makes things a bit shorter.
I am using PostgreSQL 8.2 and I am also new to PostgreSQL.
I have to add one condition in the WHERE clause depending upon specific value (49) of the field (activity.type). Here is my Query:
SELECT activity.*
FROM activity
LEFT JOIN event_types ON activity.customstatusid = event_types.id, getviewableemployees(3222, NULL) AS report
WHERE
(
CASE WHEN activity.type = 49 THEN
'activity.individualid IN(SELECT individualid from prospects where prospects.individualid = activity.individualid)'
ELSE 1
END
)
AND activity.date BETWEEN '2016-10-01' AND '2016-10-06'
AND activity.type IN (21, 22, 49, 50, 37, 199)
AND (event_types.status = 1 or event_types.status IS NULL);
When I run above query in the command line access of PGSQL then I get below error:
ERROR: invalid input syntax for integer: "activity.individualid IN(SELECT individualid from prospects where prospects.individualid = activity.individualid)"
What I am missing here?
Implement your where clause as:
WHERE (
activity.type != 49 OR
activity.individualid IN (
SELECT individualid from prospects
WHERE prospects.individualid = activity.individualid)
)
AND activity.date BETWEEN '2016-10-01' AND '2016-10-06'
AND activity.type IN (21, 22, 49, 50, 37, 199)
AND (event_types.status = 1 or event_types.status IS NULL);
The first clause will only be true when either:
activity.type != 49; or
activity.type == 49 and activity.individualid is found in the subquery.
Does anyone know a good way to detect if the result from current_query()is a prepared statement or not?
I seems that I can't simply use a string function because this would be an exampe for a prepared statement:
UPDATE table SET "x" = $1 WHERE "y" = $2 AND "z" = $3
But this would not:
UPDATE table SET "x" = '$1 + $2 = $3' WHERE "y"='$1' AND "z" = 1
Is there maybe another function I can use together with / instead of current_query() or do you have any other ideas?
You may be able to detect if current_query() is a prepared statement by looking for \$[[:digit:]] after stripping the text of all strings. The following query would do, however it may fail in cases of intricate quote nesting:
with
queries(curr_query) as (
values ($$UPDATE table SET "x" = '$1||''a'' + $2 = $3' WHERE "y"='$1' AND "z" = 1$$),
($$UPDATE table SET "x" = $r1$a$r1$||$1 WHERE "y" = $2 AND "z" = $3||$r1$b$r1$ $$),
($$UPDATE table SET "x" = $1 WHERE "y" = $2 AND "z" = $3$$)
),
stripped as (
select *,
regexp_replace(
regexp_replace(
regexp_replace(curr_query, '(["'']).*?\1', '', 'g'),
'\$([[:alpha:]]*?)\$.*?\$\1\$', '', 'g'),
'\$([[:alpha:]][[:alnum:]]*?)\$.*?\$\1\$', '', 'g') as stripped_query
from queries
)
select *, stripped_query ~ '\$[[:digit:]]' AS is_prepared
from stripped
I have a huge query which uses case/when often. Now I have this SQL here, which does not work.
(select case when xyz.something = 1
then
'SOMETEXT'
else
(select case when xyz.somethingelse = 1)
then
'SOMEOTHERTEXT'
end)
(select case when xyz.somethingelseagain = 2)
then
'SOMEOTHERTEXTGOESHERE'
end)
end) [ColumnName],
Whats causing trouble is xyz.somethingelseagain = 2, it says it could not bind that expression. xyz is some alias for a table which is joined further down in the query. Whats wrong here? Removing one of the 2 case/whens corrects that, but I need both of them, probably even more cases.
SELECT
CASE
WHEN xyz.something = 1 THEN 'SOMETEXT'
WHEN xyz.somethingelse = 1 THEN 'SOMEOTHERTEXT'
WHEN xyz.somethingelseagain = 2 THEN 'SOMEOTHERTEXTGOESHERE'
ELSE 'SOMETHING UNKNOWN'
END AS ColumnName;
As soon as a WHEN statement is true the break is implicit.
You will have to concider which WHEN Expression is the most likely to happen. If you put that WHEN at the end of a long list of WHEN statements, your sql is likely to be slower. So put it up front as the first.
More information here: break in case statement in T-SQL
declare #n int = 7,
#m int = 3;
select
case
when #n = 1 then
'SOMETEXT'
else
case
when #m = 1 then
'SOMEOTHERTEXT'
when #m = 2 then
'SOMEOTHERTEXTGOESHERE'
end
end as col1
-- n=1 => returns SOMETEXT regardless of #m
-- n=2 and m=1 => returns SOMEOTHERTEXT
-- n=2 and m=2 => returns SOMEOTHERTEXTGOESHERE
-- n=2 and m>2 => returns null (no else defined for inner case)
If logical test is against a single column then you could use something like
USE AdventureWorks2012;
GO
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO
More information - https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql?view=sql-server-2017
OK, the umpteenth conditional column question:
I'm writing a stored proc that takes an input parameter that's mapped to one of several flag columns. What's the best way to filter on the requested column? I'm currently on SQL2000, but about to move to SQL2008, so I'll take a contemporary solution if one's available.
The table queried in the sproc looks like
ID ... fooFlag barFlag bazFlag quuxFlag
-- ------- ------- ------- --------
01 1 0 0 1
02 0 1 0 0
03 0 0 1 1
04 1 0 0 0
and I want to do something like
select ID, name, description, ...
from myTable
where (colname like #flag + 'Flag') = 1
so if I call the sproc like exec uspMyProc #flag = 'foo' I'd get back rows 1 and 4.
I know I can't do the part in parens directly in SQL. In order to do dynamic SQL, I'll have to stuff the entire query into a string, concatenate the #flag param in the WHERE clause and then exec the string. Aside from the dirty feeling I get when doing dynamic SQL, my query is fairly large (I'm selecting a couple dozen fields, joining 5 tables, calling a couple of functions), so it's a big giant string all because of a single line in a 3-line WHERE filter.
Alternately, I could have 4 copies of the query and select among them in a CASE statement. This leaves the SQL code directly executable (and subject to syntax hilighting, etc.) but at the cost of repeating big chunks of code, since I can't use the CASE on just the WHERE clause.
Are there any other options? Any tricky joins or logical operations that can be applied? Or should I just get over it and exec the dynamic SQL?
There are a few ways to do this:
You can do this with a case statement.
select ID, name, description, ...
from myTable
where CASE
WHEN #flag = 'foo' then fooFlag
WHEN #flag = 'bar' then barFlag
END = 1
You can use IF.
IF (#flag = 'foo') BEGIN
select ID, name, description, ...
from myTable
where fooFlag = 1
END ELSE IF (#flag = 'bar') BEGIN
select ID, name, description, ...
from myTable
where barFlag = 1
END
....
You can have a complicated where clause with a lot of parentheses.
select ID, name, description, ...
from myTable
where (#flag = 'foo' and fooFlag = 1)
OR (#flag = 'bar' and barFlag = 1) OR ...
You can do this with dynamic sql:
DECLARE #SQL nvarchar(4000)
SELECT #SQL = N'select ID, name, description, ...
from myTable
where (colname like ''' + #flag + 'Flag'') = 1'
EXECUTE sp_ExecuteSQL #SQL, N''
There are more, but I think one of these will get you going.
"Alternately, I could have 4 copies of the query and select among them in a CASE statement."
You don't need to copy your entire query 4 times, just add all the possibilities into the where clauses in your single copy of the query:
select ID, name, description, ...
from myTable
where (#flag = 'foo' and fooFlag = 1) OR (#flag = 'bar' and barFlag = 1) OR ...
What I would do is CASE some variables at the beginning. Example:
DECLARE
#fooFlag int,
#barFlag int,
#bazFlag int,
#quuxFlag int
SET #fooFlag = CASE WHEN #flag = 'foo' THEN 1 ELSE NULL END
SET #barFlag = CASE WHEN #flag = 'bar' THEN 1 ELSE NULL END
SET #bazFlag = CASE WHEN #flag = 'baz' THEN 1 ELSE NULL END
SET #quuxFlag = CASE WHEN #flag = 'quux' THEN 1 ELSE NULL END
SELECT ID, name, description, ...
FROM myTable
WHERE (fooFlag >= ISNULL(#fooFlag, 0) AND fooFlag <= ISNULL(#fooFlag, 1))
AND (barFlag >= ISNULL(#barFlag, 0) AND barFlag <= ISNULL(#barFlag, 1))
AND (bazFlag >= ISNULL(#bazFlag, 0) AND bazFlag <= ISNULL(#bazFlag, 1))
AND (quuxFlag >= ISNULL(#quuxFlag, 0) AND quuxFlag <= ISNULL(#quuxFlag, 1))
The good thing about this query is that, because the possible values for "flags" are bounded, you can calculate all your conditionals as prerequisites instead of wrapping columns in them. This guarantees a high-performance index seek on whichever columns are indexed, and doesn't require writing any dynamic SQL. And it's better than writing 4 separate queries for obvious reasons.
You could have a parameter for each possible flag column, then check if the parameter is null or the value in the column is equal to the parameter. Then you pass in a 1 for the flags that you want to check and leave the others null.
select id, name, description, ...
from myTable
where (#fooFlag is null or fooFlag = #fooFlag) AND
(#barFlag is null or barFlag = #barFlag) AND
...
Honestly, though, this seems like an ideal candidate for building a dynamic LINQ query and skipping the SPROC once you get to SQL2008.
int should be accepted as varchar value
declare #CompanyID as varchar(10) = '' -- or anyother value
select * from EmployeeChatTbl chat
where chat.ConversationDetails like '%'+#searchKey+'%'
and
(
(0 = CASE WHEN (#CompanyID = '' ) THEN 0 ELSE 1 END)
or
(chat.CompanyID = #CompanyID)
)
working
when the companyID is present , then filtration based on it is done, other wise , filtration is skipped.
where
case when #value<>0 then Field else 1 end
=
case when #value<>0 then #value else 1 end