SQL Server functional equivalent to PostgreSQL "in" - sql-server

In postgres you can do a comparison against multiple items like so:
SELECT 'test' IN ('not','in','here');
Which is the same as doing:
SELECT ('test' = 'not' OR 'test' = 'in' OR 'test' = 'here');
Is there a functional equivalent for SQL Server ?

It is supported, but you will need to put the expression somewhere that accepts a boolean expression. For example, in a case statement:
select case when 'test' in ('not','in','here') then 1 else 0 end
-----------
0
(1 row(s) affected)
Or a where clause:
select * from T where C in (1,3,5,7,9)

this should give similar results in all recent versions of MSSQL. You could also write a scalar function to shorten things up a bit.
select case
when 'test' IN ('not', 'in', 'here') then 1
else 0
end;

This will give 1 if 'test' is in the comparison set 1 or more times, or 0 if it isn't.
SELECT CAST(COUNT(*) AS BIT) as IsItHere WHERE 'test' IN('not','in','here')
Note that the cast isn't strictly necessary, but may be useful if this is called from another language... It should then resolve to a boolean.
EDIT: According to MSSQL Query planner, this is executed ~4 times faster then the CASE method. YMMV.

Related

SSIS Execute SQL Task Error "Single Row result set is specified, but no rows were returned."

I am attempting what I thought was a relatively easy thing. I use a SQL task to look for a filename in a table. If it exists, do something, if not, do nothing.
Here is my setup in SSIS:
My SQL Statement in 'File Exists in Table' is as follows, and ResultSet is 'Single Row':
SELECT ISNULL(id,0) as id FROM PORG_Files WHERE filename = ?
My Constraint is:
When I run it, there are no files in the table yet, so it should return nothing. I've tried ISNULL and COALESCE to set a value. I receive the following error:
Error: 0xC002F309 at File Exist in Table, Execute SQL Task: An error occurred while assigning a value to variable "id": "Single Row result set is specified, but no rows were returned.".
Not sure how to fix this. The ISNULL and COALESCE are the things suggestions found in SO and on MSDN
Try changing your SQL statement to a COUNT then your comparison expression would read #ID > 0. So, if you have files that match your pattern the count will be greater than 0 if there are no files it will return 0.
SELECT COUNT(id) as id FROM PORG_Files WHERE filename = ?
If you want to check if a row exists then you should use Count as #jradich1234 mentioned.
SELECT COUNT(*) as id FROM PORG_Files WHERE filename = ?
If you are looking to check if a row exists and to store the id in a variable to use it later in the package, first you have to use TOP 1 since you selecting a single row result set and you can use a similar logic:
DECLARE #Filename VARCHAR(4000) = ?
IF EXISTS(SELECT 1 FROM PORG_Files WHERE filename = #Filename)
SELECT TOP 1 id FROM PORG_Files WHERE filename = #Filename
ELSE
SELECT 0 as id
Then if id = 0 then no rows exists.
It just needs to use UNION another row empty
always return a value
Like it if work for you
SELECT foo As nameA, fa AS nameB
UNION ALL
SELECT NULL AS nameA, NULL AS nameB
And then you can validated (line) contrained if var is null no allow

SQL Report Error - [Macromedia][SQLServer JDBC Driver][SQLServer]Invalid column name

We use a housing software based on ColdFusion and uses SQL to create database functions in our reports. I am working on a custom report to try to subtract one column from another: more specifically subtract COUNT_OF_INSPECTION_TYPE from OCCUPANCY. The OCCUPANCY column is based on the following code:
CONVERT(INT
, CASE
WHEN tblHalls.HALLNAME = 'Hall1' THEN 198
WHEN tblHalls.HALLNAME = 'Hall2' THEN 430
WHEN tblHalls.HALLNAME = 'Hall3' THEN 333
END
)
When I try a new function OCCUPANCY - COUNT_OF_INSPECTION_TYPE, I get an error:
Unable to invoke CFC - Error Executing Database Query. [Macromedia][SQLServer JDBC Driver][SQLServer]Invalid column name
'OCCUPANCY'.
I'm not sure if I am explaining this right. I'd appreciate any help you can offer.
You cannot create an alias and use it in another calculation, at the same level, because the alias is not defined yet. Either repeat the whole CASE ... END statement in the calculation (less desirable) OR use another option, such as a CTE, derived table, APPLY operator, etcetera.
Wrapping your existing SELECT in a CTE is probably one of the simplest options:
;WITH cte
AS
(
-- Your current SELECT statement goes here
SELECT
CONVERT(INT
, CASE
WHEN tblHalls.HALLNAME = 'Hall1' THEN 198
WHEN tblHalls.HALLNAME = 'Hall2' THEN 430
WHEN tblHalls.HALLNAME = 'Hall3' THEN 333
END
)
AS OCCUPANCY
, tblHalls.COUNT_OF_INSPECTION_TYPE
, ... (Other Columns)
FROM tblHalls
)
-- Now use the alias in a calculation
SELECT cte.*
, cte.OCCUPANCY - cte.COUNT_OF_INSPECTION_TYPE AS SomeAliasForThisCol
FROM cte
Side note, since the CASE statement does not define an ELSE condition, the result of the calculation will be NULL if none of HallName's match. If that is not desirable, consider setting a default.

Is there a better way to check the database for a unique value that works for both update and insert then below

IF EXISTS(SELECT * FROM MyTable WITH (NOLOCK) WHERE MyTable.RecordId <> #RecordId AND MyTable.UniqueColumn = #UniqueValue)
BEGIN
SELECT 1
END
ELSE
BEGIN
SELECT 0
END
NOTE: I use the NOLOCK so it checks for pending inserts and update (i.e someone update / changing the UniqueColumn)
NOTE: I use the "IF EXISTS(" so it stops search after finding the first match
NOTE: I use the "MyTable.RecordId <> #RecordId" so that it does not find itself as a match.
NOTE: If inserting the recordId would be negative one or zero.
Don't know if it's "better", but it's more to-the-point:
select
case
when
exists ( select * from ... where ... )
then 1
else 0
end as IsThereOrNot
...and can be used with other expressions (if you need 'em).
Note: select * is appropriate for existence checks, and nolock isn't going to change anything - there's an implicit transaction for the scope of the select.
I think it's better (easier to use the results by your consumers) if you name your columns (IsThereOrNot in the example)

Determine if T-SQL select statement returns any rows

I am using Microsoft SQL Server 2012. I want to set a boolean value in a stored procedure. I want to set the value to true if a certain select query returns more than zero rows.
Declare #ShowQuotingTool as bit
(select count(*) from tblAgentsLicensedState where AgentCode = '016893' and StateCode in ('AZ','GA','IA', 'TN', 'SC', 'KS', 'MI' ,'NC', 'UT')) > 0;
How do I set #ShowQuotingTool to true or false based on the select query? I get the error Incorrect syntax near ">".
You can just assign #ShowQuotingTool to the count query. This is based on the fact that any count > 0 will set the bit variable #ShowQuotingTool to true and count = 0 will set it to false
Declare #ShowQuotingTool as bit
SELECT #ShowQuotingTool = (select count(*) from tblAgentsLicensedState where AgentCode = '016893' and StateCode in ('AZ','GA','IA', 'TN', 'SC', 'KS', 'MI' ,'NC', 'UT'))
You should preferably use EXISTS which would have better performance than COUNT query above.
IF EXISTS(select * from tblAgentsLicensedState where AgentCode = '016893' and StateCode in ('AZ','GA','IA', 'TN', 'SC', 'KS', 'MI' ,'NC', 'UT'))
SET #ShowQuotingTool = 1
ELSE
SET #ShowQuotingTool = 0
Good Day,
Please post DDL+DML if this is not what you are looking for. In any case please remember next time to post DDL+DML (queries to create the relevant tables and to insert some sample data, in order to give us the tools to reproduce the issue).
Back to your question:
If you have an SP that return the result of select query (or any DML query), that mean that you need this query to execute as it is. The idea of using COUNT function on the results mean that you execute another query, which is not logic action to do, since we already have the information in the headers of the result.
If you notice, by default, every time that you execute a query in the SSMS for example you get the information regarding number of rows: "(x row(s) affected)". There is no need to use another query.
If you are using external application that you develop, and your SP do not use "SET NOCOUNT ON", then this information coming back from the server :-)
You can see examples here:
https://msdn.microsoft.com/en-us/library/ms171921.aspx?f=255&MSPPError=-2147217396

How do I return two recordcounts from an Execute SQL Task to User variables in an SSIS package

I've got a package in SSIS 2012 that has an Execute SQL task in the control flow level.
The SQL in question does an Upsert via the SQL merge statement. What I want to do, is return the count of records inserted and records updated (No deletes going on here to worry about). I'm using the output option to output the changed recs to a table variable.
I've tried returning the values as:
Select Count(*) as UpdateCount from #mergeOutput where Action = 'Update'
and
Select Count(*) as InsertCount from #mergeOutput where Action = 'Insert'
I've tried setting the resultset to both Single rowset and Full rowset, but i'm not seeing anything returned to the package variables I've set for them (intInsertcount and intUpdatecount).
What am I doing wrong?
Thanks.
You should try the following:
Select UpdateCount = (Select Count(*) as UpdateCount from #mergeOutput where Action = 'Update'),
InsertCount = (Select Count(*) as InsertCount from #mergeOutput where Action = 'Insert')
Using a single result set this should give you an output along the lines of
UpdateCount | InsertCount
# | #
Then just map the result set changing the name of each result and use breakpoints to test and makesure the variables update through the process.
This is what I use when I want to return multiple result sets from different tables in the same query, however I don't know how it works with the output of merge statements.
Set the Execute SQL command output as single line
SqlCommand as :
Select sum(case when Action='Update' then 1 else 0 end) Update_count,
sum(case when Action='Insert' then 1 else 0 end) Insert_count
from #mergeOutput;
In the Result set tab click on the Add button; set your variables to point to the 2 outputs of the above query, positionally:
0 => intUpdatecount; 1 => intInsertcount

Resources