sql query - get all records based on a flag - sql

Apologies for creating a new thread. I was not able to frame the question correctly in the previous thread.
I have a table in SQL Server 2008 that looks like this -
Id Status
--------------
1 A
2 I
3 NULL
I have a stored procedure which takes #Status as the parameter.
If the #Status is "-1", I need to retrieve records 1, 2.
If the #Status is "A", I need to retrieve only record 1.
If the #Status is "I", I need to retrieve only record 2.
I want to be able to retrieve the records in a single SELECT statement without using IF ELSE. There are a lot of joins and stuff in the SELECT statement and I don't want to repeat the same thing in the ELSE condition.
I have tried the following but get incorrect data -
SELECT * FROM Person WHERE Status = #Status OR #Status IS NOT NULL
select * from Person
where (#Status is not null and Status = #Status) or
(#Status is null and Status in ('A', 'P'))

You can do it using OR:
SELECT *
FROM Person
WHERE Status = #Status
OR (#Status = '-1' AND Status IS NOT NULL)
Of course you shouldn't use SELECT * in production code.

Related

How to Update a column Before Select?

I am setting a stored procedure for select and I want to update the value of one column in the database Before doing the Select.
This is what I tried but it's not working.
#roleID int and #query varchar(240)
SELECT
EP.Equipe_Projet_Id AS PROJET_ID,
U.USR_ID,
CleRepartition = CASE
WHEN #RoleID = 1 AND #query IS NOT NULL
THEN 100
AND (UPDATE EQUIPE_PROJET SET CleRepartition = 100
WHERE EP.Equipe_Projet_Id = #PROJET_ID AND EP.Role_Id = 3)
ELSE NULL
END
FROM
[EQUIPE_PROJET] EP
Expecting update of column on database and having it's value
i want to update the value of Column CleRepartition in the database while selecting.
This is not possible in a SELECT query. A SELECT retrieves data from the database. An UPDATE modifies data. These are two separate statements and cannot be combined.
You are doing this work in a stored procedure. Within a stored procedure, you can run an UPDATE and SELECT in any order, so you can accomplish both tasks. If you are concerned about data changing in the database between the two statements, you can wrap them in a transaction.
Stored procedure can do update then select after.
So I added the query of update in the beginning, then I do the select.
Like this:
UPDATE EP
SET CleRepartition = CASE
WHEN #RoleID = 1 AND #query IS NOT NULL
THEN 100
AND (UPDATE EQUIPE_PROJET
SET CleRepartition = 100
WHERE EP.Equipe_Projet_Id = #PROJET_ID
AND EP.Role_Id = 3)
ELSE NULL
END
FROM [EQUIPE_PROJET] EP
SELECT
EP.Equipe_Projet_Id AS PROJET_ID,
U.USR_ID,
CleRepartition
FROM
[EQUIPE_PROJET] EP
I hope that this will help someone.

query: if condition in sql server update

I have a SQL server table in which there are 2 columns that I want to update either of their values according to a flag sent to the stored procedure along with the new value, something like:
UPDATE
table_Name
SET
CASE
WHEN #flag = '1' THEN column_A += #new_value
WHEN #flag = '0' THEN column_B += #new_value
END AS Total
WHERE
ID = #ID
What is the correct SQL server code to do so??
I thought M.Ali's comment was correct, so I've constructed this based on his suggestion.
I'm also assuming the status field is 'approved' or 'declined' as you say based on if it's populated or not. If there are any other conditions on the status field, offcourse you must add these to you where statements
BEGIN TRANSACTION
Update Payment
set post_date = new_postdate_value
account_num = new_account_num_value
pay_am = new_pay_am_value
pay_type = new_pay_type_value
authoriz = new_authoriz_value
where status is not null
UPDATE Payment
SET account_num = new_account_num_value
WHERE status is null
COMMIT TRANSACTION

Need to wait on specific column state change in SQL

I need to check for the status change of a certain column in the table
I can do it using while loop, where i can get the column value and check the value and break from the loop if value is changed.
i am using SQL server 2008.
is there a better way?
Here is the sample sql query
declare #status int = 1
select #status = status from MyTable with (nolock) where Id = 100034
while #status <> 3
begin
WAITFOR DELAY '00:01'
select #status = status from MyTable with (nolock) where Id = 100034
end
Have you considered to use a trigger instead of an stored procedure? This is exactly, what are triggers for.
CREATE TRIGGER reactOnStatus3
ON MyTable
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
IF Status = 3
EXEC DoTheMagicStoredProcedure;
END;

Read uncommited data in smple connect

Is it possible (in SQL SERVER 2012) to read data before update in one transaction.
Example:
I have one table, name: tab with two columns col1 and col2. I have one record: col1 = 1 and col2 = 'a'
begin transaction
update tab set col2 = 'A' where col1 = 1
-- here i want to read data before update (in this example 'a')
-- here i want to read data after update (in this example 'A')
Committ transaction
Before committ transaction when using select always i get data after update (in this example 'A'). I try to do
select * from tab with(nolock)
but it doesn't work.
Question: In section: after update and before committ - can i read data which was before update ?
Thanks.
Locking hints determine how nicely you read data that is being updated by another transaction. But code that runs in a transaction always sees changes made earlier in the same transaction.
If you need the old state, why not store the old version in a variable? Like:
begin transaction
declare #old_col2 int
select #old_col2 = col2 from tab where id = 1
update tab set col2 = 'A' where id = 1
... now you can access both the old and the new data ...
You can achieve the same using below sample :
USE AdventureWorks2012;
GO
DECLARE #MyTableVar table(
EmpID int NOT NULL,
OldVacationHours int,
NewVacationHours int,
ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25,
ModifiedDate = GETDATE()
OUTPUT inserted.BusinessEntityID,
deleted.VacationHours,
inserted.VacationHours,
inserted.ModifiedDate
INTO #MyTableVar;
--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM #MyTableVar;
GO
--Display the result set of the table.
SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO
This is elegant solution instead of writing seperate SELECTs in the code.
Reference http://msdn.microsoft.com/en-IN/library/ms177564.aspx

SQL Query...nulls hosing me

I tried to ask this question before but I don't think I explained myself very well. So here it is: asp.net 2.0 app hitting a SQL 2008 backend. This seems simple but I can't get it. 1 table. The user selects a status. The query should return all records = the chosen status only. If the user select "All Status", then ALL records should be returned, including those with a status = null (which is the part that is hosing me).
Ex:
CASE 1: User selects Status = "Satisfied"; ONLY satisfied records are return
CASE 2: User selects All Status = everything is returned, satisfied AND nulls and anything else
I tried passign in a wildcard but this doesn't return nulls. I tried dynamically buildign the query but I would like to avoid it.
For the case where you want them all, how about: (am I missing something?)
SELECT * FROM <tablename>
SELECT * FROM <tablename> WHERE Status = '*' OR Status IS NULL
...or '%' or whatever wildcard your SQL implementation uses.
...or if you really have no other conditions following this, just select *...
Try this in a stored procedure.
--Pass in #status as a parameter
DECLARE #Status varchar(100)
IF #Status = 'All Status'
BEGIN
SELECT * FROM tablename
END
ELSE
BEGIN
SELECT * FROM tablename where statusfield = #Status
END
One option is
declare #status varchar(50)
SELECT * FROM <tablename> WHERE (#status is null) or (Status = #status)
if you pass null in for the #status parameter then it will return all records. If you pass 'satisfied' or whatever then it will return just those matchng records.
If doing this in SQL 2008, be sure you have SP1 and Cumulative Update 5 installed. Further, I would recommend adding the WITH RECOMPILE option to the procedure. Under those conditions it will be as performant as embedded SQL or even using unions.
See the following article for an indepth discussion of the myriad of ways to perform searching in SQL 2008: Dynamic Search Conditions in T-SQL
The problem is that SQL's = operator always returns NULL when one of the operands is NULL, so using status = '%' indeed doesn't work. The best method is to just not include a condition on status if you want all of them. You can add extra NULL tests to the query, but that again is building it dynamically, I don't see a way to avoid that...
basically your statement will be for 'Statisfied'
SELECT * FROM testtab WHERE
COALESCE(statuscolumn, '') LIKE '%Statified'
for 'All Status' it will be
SELECT * FROM testtab WHERE
COALESCE(statuscolumn, '') LIKE '%'
you could use this statment and if selection is 'All Status' then pass a '' for the #status from your UI
SELECT * FROM testtab WHERE
COALESCE(statuscolumn, '') LIKE '%' || #status
Or you can use this one and when you pass the selection from UI make sure it has a '%' (wild char) appended to your status when it not 'All Status'. When its 'All Status' just pass '%' for the #status
SELECT * FROM testtab WHERE
COALESCE(statuscolumn, '') LIKE #status
oh your db is mssql? :) then you will need to replace the collace(statuscolumn, '') with isnull(statuscolumn, '').
Just skip the where clause or the part that is about the status field, example:
SELECT * from table_1 Where status = 'Satisfied'
and
SELECT * from table_1
When you want all records, you have to exclude STATUS from your WHERE clause (or use a UNION and a select statement where STATUS IS NULL).
Depending on what version of SQL you are using, you might be able to use an IF..ELSE... statement.
IF Status='ALL' THEN
... A SELECT statement where STATUS is NOT included in the WHERE
ELSE
... A SELECT statement that has a WHERE with only the status you are looking for
SELECT * FROM <tablename> WHERE isnull(Status,'*') = '*'
Assuming you're passing a variable to an SP:
SELECT * FROM Table WHERE Status CASE #status WHEN 'All status' THEN Status ELSE #status END
Otherwise, you need to concatenate in the selected value within quotes at both places where it currently says #status
The idea is what to do when the users chooses 'All Status'. By setting the param to NULL, you can use the isnull and then each [status] field just needs to equal itself. I've used ISNULL to set to '' to avoid having NULL = NULL>
declare #param_choice varchar(25)
if #param_choice = 'All Status'
Begin
#param_choice = NULL
End
-- get your results
Select * from Some_Table
Where IsNull([Status], '') = IsNull(#param_choice, IsNull([Status], ''))
You'll get the best performance from:
IF #status IS NULL
BEGIN
SELECT t.*
FROM TABLE t
END
ELSE
BEGIN
SELECT t.*
FROM TABLE t
WHERE t.status = #status
END
The next option is to use:
SELECT t.*
FROM TABLE t
WHERE (#status IS NULL OR t.status = #status)
...but that is not sargable.
I do not believe that anyone suggested using a UNION.
SELECT t.*
FROM TABLE t
WHERE (#status IS NULL)
UNION ALL
SELECT t.*
FROM TABLE t
WHERE (t.status = #status)
If #status is NULL, then the first query in the union is executed, and t.status = #status is clearly always false, so the second query in the union is not executed at all.
If #status is not null, then the first query in the union is not exected at all, and the second one is.
Importantly, since ISNULL, COALESCE or a function are not used on t.status or on #status, then if there is an index on status, it can be used. That is, the predicate is SARGABLE.
And I used UNION ALL (instead of UNION) to prevent a SORT and DISTINCT operation that can be very slow.