SSIS SQL Task Unable to assign Parameter Value when using IF EXISTS - sql-server

I'm using VS 2012 and SQL Server / SSIS.
I originally had a SQL task to check for duplicate values in a table:
SELECT COUNT(*) AS DupNI
FROM dbo.mytable
WHERE XMLFileID = ?
GROUP BY XMLFileID, NINumber
HAVING (COUNT(*) > 1);
The ? is because I am inserting a parameter value, and the result of the query is being assigned to a variable. It works fine if there is a duplicate.
When there are no duplicates, I get this message:
Single Row result set is specified, but no rows were returned
So, to get round this I now use an IF EXISTS, like the below:
IF EXISTS (SELECT COUNT(*) AS DupNI
FROM dbo.mytable
WHERE XMLFileID = ?
GROUP BY XMLFileID, NINumber
HAVING (COUNT(*) > 1))
SELECT COUNT(*) AS DupNI
FROM dbo.mytable
WHERE XMLFileID = ?
GROUP BY XMLFileID, NINumber
HAVING (COUNT(*) > 1)
ELSE
SELECT 0 AS DupNI;
However, now I get the error:
No value given for one or more required parameters.
It appears because I am wrapping the statement in the IF EXISTS, I can no longer inject the parameter values via the ?
Why is this? How do I get around this issue?

Your current query will return multiple rows if there are duplicates, one for each duplicate (XMLFileID, NINumber) pair. If you only want to return a value which indicates whether there are any duplicates in the table, you could use your EXISTS clause as an expression:
SELECT CASE WHEN EXISTS(
SELECT COUNT(*) AS DupNI
FROM dbo.mytable
WHERE XMLFileID = ?
GROUP BY XMLFileID, NINumber
HAVING (COUNT(*) > 1)
) THEN 1 ELSE 0 END AS [Duplicates Exist]
Demo on dbfiddle

Related

Gives me error while execution "object is not valid"

I want to delete the duplicate records from the table So I used the CTE option but i am getting the below error message. What will be the cause? Am I did anything wrong? Upto select statement it works.
with Empcte as (
select *
, ROW_NUMBER() over (partition by ID ORDER BY ID) as RowNumber
from Empgender
)
SELECT *
FROM Empcte
delete from Empcte
where RowNumber > 1
Msg 208, Level 16, State 1, Line 8
Invalid object name 'Empcte'.
You can't use the same CTE for two different statements. (in this case first a SELECT and then a DELETE) You either have to re-create the CTE for the DELETE, or use a temp table or table variable instead of a CTE.
A CTE is a disposable view. It only persists for a single statement, and then disappears automatically. You can just avoid the SELECT statement:
WITH Empcte as (
SELECT id
,Count() as Rowcount
FROM Empgender
Group by id)
DELETE from Empgender where
Exists ( select 1 from Empgender as eg where Empcte.id = eg.id and Empcte.Rowcount >1 and );

Execution of ISNULL in SQL Server

Here is how i am using ISNULL condition to check for student address.
It works fine but how ISNULL function treat the null codition i.e the second parameter which is display if first condition is null.
Will it calculate Value for second parameter when first condition is not null?
select
...
...
(CASE
WHEN st.ADDRESS='Y' THEN st.LOCATION
ELSE
ISNULL(
(SELECT TOP 1 STDLOC.LOCATION FROM STDLOC
INNER JOIN COMLOC ON STKLOC.LOCATION=COMLOC.CODE AND COMLOC.ADDRESS='Y'
WHERE STDLOC.ZIBCODE=st.ZIBCODE)
,(SELECT TOP 1 COMLOC.LOCATION FROM COMLOC COMLOC.ZIBCODE=st.ZIBCODE))
END
) AS STDUDENTLOCATION
FROM STUDENT st
Both queries inside the ISNULL will be executed, even if the first query will return a value.
Here is a simple test I've made:
Create and populate sample table:
DECLARE #T AS TABLE
(
Col int
)
INSERT INTO #T Values(1),(2)
SELECT ISNULL(
(SELECT TOP 1 Col FROM #T ORDER BY Col DESC),
(SELECT TOP 1 Col FROM #T ORDER BY Col )
)
Execution plan image:
As you can clearly see, the execution plan includes both queries.
I also was looking for an answer. After some reading I came out with my own way to check it.
Deviding by zero will give an error, so we can try:
SELECT ISNULL( (SELECT TOP 1 object_id FROM sys.columns), 5 / 0)
This will give correct result. BUT
SELECT ISNULL( (SELECT TOP 0 object_id FROM sys.columns), 5 / 0)
It will throw an error, because result of first query gives NULL so it tries the second query which fails
ISNULL is a T-SQL specific function that will use the specified second parameter as the return value if the first parameter is NULL(https://msdn.microsoft.com/en-us/library/ms184325.aspx).
Use COALESCE function if you want to return the first non-null value from multiple arguments, and this is a standard function that is supported by all types of relational databases.
This POST provide a good answer for the question:
Is Sql Server's ISNULL() function lazy/short-circuited?

Sub query returning all values and then applying where condition

I am having an issue with a query only in one particular environment/database even if the data is almost similar. Here is the simplified scenario:
Table A - One column - Id (long)
Id
1
2
3
Table B - Two columns - value(varchar) and field2(varchar)
Value Field2
1)abc NotKey
2)Test NotKey
3)1 Key
4)1.56 NotKey
When I run the query
select * from table a
where id in(select value from table b where Field2 = 'Key')
I get the error
Result: Conversion failed when converting the varchar value 'abc' (earlier I had this value erraneously as 'NotKey') to data type int.
on one database. In three other databases, the value returns correctly as "1".
I am using SQL Server 2008. What might be the issue here?
You gave the wrong filter for the filter that leads to the error.
The errror only happens when you select:
select * from tablea
where id in(select value from tableb where Field2 = 'NotKey')
You have to cast one of the columns
select * from tablea
where cast( id as nvarchar(20)) in(select value from tableb where Field2 = 'NotKey')
http://sqlfiddle.com/#!6/e9223/23
You must have a record in this instance that doesn't follow the same pattern as before. Try running the following query to find your bad data. You could either fix the record or add a numeric check to the query you're using.
select *
from table
where Field2 = 'Key'
and (ISNUMERIC(Value) = 0
OR CHARINDEX('.', Value) > 0);
Filtered query:
select *
from table a
where id in
(
select value
from table b
where Field2 = 'Key'
and ISNUMERIC(value) = 1
and CHARINDEX('.', Value) = 0
);

How to compare records in same SQL Server table

My requirement is to compare each column of row with its previous row.
Compare row 2 with row 1
Compare row 3 with row 2
Also, if there is no difference, I need to make that column NULL. Eg: request_status_id of row 3 is same as that of row 2 so I need to update request_status_id of row 3 to NULL.
Is there a clean way to do this?
You can use the following UPDATE statement that employs LAG window function available from SQL Server 2012 onwards:
UPDATE #mytable
SET request_status_id = NULL
FROM #mytable AS m
INNER JOIN (
SELECT payment_history_id, request_status_id,
LAG(request_status_id) OVER(ORDER BY payment_history_id) AS prevRequest_status_id
FROM #mytable ) t
ON m.payment_history_id = t.payment_history_id
WHERE t.request_status_id = t.prevRequest_status_id
SQL Fiddle Demo here
EDIT:
It seems the requirement of the OP is to SET every column of the table
to NULL, in case the previous value is same as the current value. In this case the query becomes a bit more verbose. Here is an example with two columns being set. It can easily be expanded to incorporate any other column of the table:
UPDATE #mytable
SET request_status_id = CASE WHEN t.request_status_id = t.prevRequest_status_id THEN NULL
ELSE T.request_status_id
END,
request_entity_id = CASE WHEN t.request_entity_id = t.prevRequest_entity_id THEN NULL
ELSE t.request_entity_id
END
FROM #mytable AS m
INNER JOIN (
SELECT payment_history_id, request_status_id, request_entity_id,
LAG(request_status_id) OVER(ORDER BY payment_history_id) AS prevRequest_status_id,
LAG(request_entity_id) OVER(ORDER BY payment_history_id) AS prevRequest_entity_id
FROM #mytable ) t
ON m.payment_history_id = t.payment_history_id
SQL Fiddle Demo here

ISNULL() returning NULL

Why does the following simple query return null when there are no matching rows (<Condition> is not met by any row)?
SELECT ISNULL(MyField, 0) FROM [MyTable] WHERE <Condition>
I have tried COALESCE() as well, with similar results. How can I return zero when there are no matching rows?
This will work, provided you expect condition to reduce the result set to either 0 or 1 row:
SELECT ISNULL((SELECT MyField FROM [MyTable] WHERE <Condition>),0)
That is, create an outer query with no FROM clause (which will therefore always generate exactly one row) and then use a subquery to obtain your 0 or 1 row of actual data.
Use this:
SELECT ISNULL(COUNT(MyField), 0) FROM [MyTable] WHERE <Condition>
It'll return 0 if row is missing.
You cannot convert 0 rows to 1 row with a null value with any sql built-in fuction because that may cause mis-interpretation of data
But you can customize your result using the below logic (same as you do in .net).
If (select COUNT(MyField) FROM [MyTable] WHERE <Condition>)=0
select 0 as [MyField]
else
SELECT ISNULL(MyField, 0) as [MyField] FROM [MyTable] WHERE <Condition>

Resources