Sum of blank values - sql

How to make sum of blank values in SQL Server?
I tried with following but returns null
Declare #val varchar
Declare #columns varchar(20)
declare #sql varchar(200)
set #columns= 'branch'
set #sql = 'select ' + #val +'= sum(case when #columns = '''' then 1 else 0 end)
from dbo.companies'
exec(#sql)
select #val
I need a dynamic SQL statement because values will be returned from stored procedure for each column.

Total stab in the dark, but I think what you're after is:
DECLARE #Count int, #Column sysname;
DECLARE #SQL nvarchar(MAX);
SET #Column = N'SomeColumnName';
SET #SQL = N'SELECT #Count = COUNT(CASE ' + QUOTENAME(#Column) + N' WHEN '''' THEN 1 END) FROM dbo.companies;';
EXEC sp_excutesql #SQL, N'#Count int OUTPUT',#Count = #Count OUTPUT;
SELECT #Count;
Edit: Note that that '' and NULL are not the same value; something that you seem to be unaware of considering you where concatenating a variable (#Val of the datatype varchar(1)) with the value NULL to a literal string. NULL + {expr} = NULL. If you want to count rows with NULL, not a blank string is IS NULL (and you'll need to move the WHEN).

Related

IF EXISTS does not return correct result

I have to check if a column in my sql table has null values and to print 'Yes'/'No'
DECLARE #columnName nvarchar(50)
SET #columnName = 'City'
IF EXISTS (SELECT 1 FROM rf.Country WHERE #columnName IS NULL)
BEGIN
PRINT 'Yes'
END
ELSE
BEGIN
PRINT 'No'
END
This query returns 'No' when I know for sure that there are null values in this column. I see that it is not allowed to use #var in WHERE statement but I need a way to loop through all columns in a table and to print result for each column if it contains NULL values.
You need to safely inject the value into a dynamic query, and then execute that:
DECLARE #ColumnName sysname; --synonym for nvarchar(128) NOT NULL
SET #ColumnName = N'City';
DECLARE #SQL nvarchar(MAX),
#CRLF nchar(2) = CHAR(13) + CHAR(10);
SET #SQL = N'IF EXISTS (SELECT 1 FROM rf.Country WHERE ' + QUOTENAME(#ColumnName) + N' IS NULL)' + #CRLF +
N' PRINT N''Yes'';' + #CRLF +
N'ELSE' + #CRLF +
N' PRINT N''No'';';
--PRINT #SQL; --Your debugging friend
EXEC sys.sp_executesql #SQL;
Your query is not checking the column values in the table. It is just checking the constant -- and #columnName IS NULL always evaluates to false because #columnName has a value.
You would need to use dynamic SQL. Perhaps:
DECLARE #columnName nvarchar(50)
SET #columnName = 'City';
SET #SQL = '
SELECT (CASE WHEN EXISTS (SELECT 1 FROM rf.Country WHERE #columnName IS NULL)
THEN 1 ELSE 0
END) as flag
';
SET #SQL = REPLACE(#SQL, '#columnName', #columnName)
DECLARE #flag INT;
EXEC sp_executeSQL #SQL,
N'#flag int OUTPUT',
#flag=#flag OUTPUT;
IF #flag = 1
PRINT 'Yes';
ELSE
PRINT 'No';
In general, I would discourage you from writing code where you need to pass column names around like this. That usually indicates a problem with the data model. I should say "usually". Under some circumstances, this can be convenient.

Set declared parameter value and CONCAT column name

I have table with columns Char1, Char2, Char3..... Each of these columns contain some value. I declared variable #i and in while loop I'm trying to concat it to the Char table column name.
Also, I declared parameter #current in my query and then I'm trying to set its value in the query.
set #tmp = cast(#i as varchar(2))
select #current = 'Char' + #tmp
from SerialNumberFormat
where Example = 'XXXXXXXXXX'
When I execute the query #current has value Char1, Char2, Char3...etc, instead the value of the column.
How I can set column value instead column name in #current?
select #current = Concat(Char1, Char2, Char3)
from SerialNumberFormat
where Example = 'X59AA419010045'
Solution which I found and works for me is executing sp_executesql stored procedure
set #SQL = N'select #currentOUT = Char' + #tmp + ' from SerialNumberFormat
where Example = ''XXXXXXXXX'''
SET #ParmDefinition = N'#currentOUT nvarchar(10) OUTPUT'
exec sp_executesql #SQL, #ParmDefinition, #currentOUT = #current OUTPUT
select #current
Dynamic Sql like this may work for you
Declare #i int = 5
Declare #tmp varChar (10) = #i
Declare #Sql nVarChar(Max) = 'select Char' + #tmp + '
from SerialNumberFormat
where Example = ''X59AA419010045'''
exec sp_executesql #Sql

Can I use variable in condition statement as value with where condition that test that value

I have the following stored procedure:
ALTER proc [dbo].[insertperoll] #name nvarchar(50) , #snum int , #gnum int
as
DECLARE #value nvarchar(10)
SET #value = 's'+CONVERT(nvarchar(50),#snum)
DECLARE #sqlText nvarchar(1000);
DECLARE #sqlText2 nvarchar(1000);
DECLARE #sqlText3 nvarchar(1000);
declare #g nvarchar(50) = '''g1'''
SET #sqlText = N'SELECT ' + #value + N' FROM dbo.GrideBtable'
SET #sqlText2 = ' where Gnumber = '+#g --here is the problem it error invalid column name -- the #g is value from the table condition
set #sqlText3 = #sqlText+#sqlText2
Exec (#sqlText3) -- here how can i save the result of the exec into varibale
declare #sal nvarchar(50) = #sqlText3
insert employ (name,Snumber,Gnumber,Salary) values(#name,#snum,#gnum,#sal)
QUESTION: How to put in condition variable gets value from the table when i exec it it think that the #g is column but its not its a value from the table to test it so i display one value after the exec the other QUESTION is how to save the result from the exec in variable and then use that value
I'm using SQL Server 2008 (9.0 RTM)
This will be a stored procedure
Thanks in advance
Not sure why you would go through all the loops to insert into the table where you can have a simple insert query like ..
ALTER PROC dbo.[insertperoll] #name nvarchar(50) , #snum int , #gnum int
AS
insert employ (name, Snumber, Gnumber, Salary)
select #name
, #sum
, #gnum
, case when #snum = 1 then s1
when #snum = 2 then s2
when #snum = 3 then s3
when #snum = 4 then s4
end as Salary
from dbo.GrideBtable
where Gnumber = #gnum
If your intent is to have the proc retrieve a salary value from a column determined from the parameter snum and then make an insert into employ using the values passed as parameters and the salary retrieved I think you could refactor your procedure to this:
CREATE proc [dbo].[insertperoll] #name nvarchar(50) , #snum int , #gnum int AS
DECLARE #g NVARCHAR(50) = 'g1'
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'INSERT employ (name,Snumber,Gnumber,Salary) '
SET #sql += N'SELECT ' + QUOTENAME(#name, '''')
SET #sql += N', ' + CAST(#snum AS NVARCHAR(50))
SET #sql += N', ' + CAST(#gnum AS NVARCHAR(50))
SET #sql += N', s' + CAST(#snum AS NVARCHAR(50))
SET #sql += N' FROM dbo.GrideBtable'
SET #sql += N' WHERE Gnumber = ' + QUOTENAME(#g, '''')
EXEC (#sql)
Of course you could add the #g variable to the procedure parameters instead of having it hard coded in the procedure and call it as:
EXEC insertperoll #name='john', #snum=10, #gnum=100, #g='g1'
Sample SQL Fiddle (with some assumptions made about table structure)
You could do this using sp_executesql instead of exec() since this will allow you to use parameters, you can use an output parameter to get the value from the query:
DECLARE #SQL NVARCHAR(MAX) = N'SELECT #val = ' + CONVERT(NVARCHAR(10),#snum) +
N' FROM dbo.GrideBtable WHERE Gnumber = #G1';
DECLARE #val INT; -- NOT SURE OF DATATYPE REQUIRED
EXECUTE sp_executesql #SQL, N'#G1 VARCHAR(20), #val INT OUT', 'G1', #val OUT;

Converting dynamic sql query's COUNT result to INT

I am trying to search within the values (table names) returned from a query to check if there is a record and some values in that record are null. If they are, then I want to insert the table's name to a temporary table. I get an error:
Conversion failed when converting the varchar value 'count(*)
FROM step_inusd_20130618 WHERE jobDateClosed IS NULL' to data type int.
This is the query:
DECLARE #table_name VARCHAR(150)
DECLARE #sql VARCHAR(1000)
DECLARE #test int
SELECT #table_name = tableName FROM #temp WHERE id = #count
SET #sql = 'SELECT * FROM ' + #table_name + ' WHERE jobDateClosed IS NULL'
--ERROR is below:
select #test = 'count(*) FROM ' + #table_name + ' WHERE jobDateClosed IS NULL'
--PRINT #sql
-- EXEC(#sql)
IF #test > 0
BEGIN
INSERT INTO #temp2 (tablename) VALUES ( #table_name);
END
SET #count = #count + 1
Any ideas how to convert the result of the count into an integer?
Check for sp_executesql where you may define output parameters.
DECLARE #table_name VARCHAR(150)
DECLARE #sql VARCHAR(1000)
DECLARE #test int
SELECT #table_name = tableName FROM #temp WHERE id = #count
DECLARE #SQLString nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
SET #SQLString = N'SELECT #test = count(*) FROM ' + #table_name + ' WHERE jobDateClosed IS NULL'
SET #ParmDefinition = N'#test int OUTPUT';
EXECUTE sp_executesql #SQLString, #ParmDefinition, #test=#test OUTPUT;
IF #test > 0
BEGIN
INSERT INTO #temp2 (tablename) VALUES ( #table_name);
END
SET #count = #count + 1
Shouldn't be "SET" instead of "select" ?
E.g., changing:
select #test = 'count(*) FROM ' + #table_name + ' WHERE jobDateClosed IS NULL'
for:
SET #test = 'select count(*) FROM ' + #table_name + ' WHERE jobDateClosed IS NULL'
As I see, your problem is, that $test variable is INT and you are trying to assign to it the TEXT value 'count ...'
Use aproach like:
SELECT somevalue INTO myvar FROM mytable WHERE uid=1;
I trimmed out the stuff not needed to show how to do this, so here it is:
DECLARE #table_name VARCHAR(150)
DECLARE #CountStatement NVARCHAR(1000)
DECLARE #test int
SELECT #table_name = tableName FROM #temp WHERE id = #count
SET #CountStatement = 'select #test = count(*) FROM ' + #table_name + ' WHERE jobDateClosed IS NULL'
EXECUTE sp_executesql #CountStatement, N'#test INT OUTPUT', #test OUTPUT;
SELECT #test

What is the best approach to filter data in SQL (Dynamic Query)?

I have a stored procedure which is supposed to return a result set from a table filtered according to parameters provided.
UPDATE
alter procedure Proc_CheckExchange
#Flag varchar(3),
#symbol varchar(13)=null,
#exchange char(3)=null,
#limit money=null,
#chargerate numeric(18,4)=null,
#ChgType char(2)=null,
#IsActive int=null,
#Mkrid varchar(11)=null,
#statecode varchar(4) =null
as
declare #sql nvarchar(max)
set #sql = N'select * from Tbl_StampDutyException1 where 1 = 1'
if(#Flag='CHK')
begin
if len(isnull(#exchange, '')) > 0
set #sql = #sql + N'and exchange=#exchange'+ cast(#exchange as nvarchar(100))
if len(isnull(#symbol, '')) > 0
set #sql = #sql + N'and symbol=#symbol'+ cast(#symbol as nvarchar(100))
if len(isnull(#limit, '')) > 0
set #sql = #sql + N'and limit=#limit'+ cast(#limit as nvarchar(100))
if len(isnull(#chargerate, '')) > 0
set #sql = #sql + N'and chargerate=#chargerate'+ cast(#chargerate as nvarchar(100))
if len(isnull(#ChgType, '')) > 0
set #sql = #sql + N'and ChgType=#ChgType'+ cast(#ChgType as nvarchar(100))
if len(isnull(#IsActive, '')) > 0
set #sql = #sql + N'and IsActive=#IsActive'+ cast(#IsActive as nvarchar(100))
if len(isnull(#statecode, '')) > 0
set #sql = #sql + N'and statecode=#statecode'+ cast(#statecode as nvarchar(100))
exec (#sql)
end
if (#Flag='ALL')
begin
select * from Tbl_StampDutyException1
end
UPDATE 1
alter procedure Proc_CheckExchange
#Flag varchar(3),
#symbol varchar(13)=null,
#exchange char(3)=null,
#limit money=null,
#chargerate numeric(18,4)=null,
#ChgType char(2)=null,
#IsActive int=null,
#Mkrid varchar(11)=null,
#statecode int =null
as
declare #sql nvarchar(max)
set #sql = N'select * from Tbl_StampDutyException1 where 1 = 1'
if(#Flag='CHK')
begin
if len(isnull(#exchange, '')) > 0
set #sql = #sql + N' and exchange = #exchange'
if len(isnull(#limit, '')) > 0
set #sql = #sql + N' and limit = #limit'
if len(isnull(#chargerate, '')) > 0
set #sql = #sql + N' and chargerate = #chargerate'
if len(isnull(#ChgType, '')) > 0
set #sql = #sql + N' and ChgType = #ChgType'
if len(isnull(#IsActive, '')) > 0
set #sql = #sql + N' and IsActive = #IsActive'
if len(isnull(#statecode, '')) > 0
set #sql = #sql + N' and statecode = #statecode'
if len(isnull(#symbol, '')) > 0
set #sql = #sql + N' and symbol = #symbol'
declare #params as nvarchar(max) = N'#Flag varchar(3),
#symbol varchar(13),
#exchange char(3),
#limit money,
#chargerate numeric(18,4),
#ChgType char(2),
#IsActive int,
#Mkrid varchar(11),
#statecode varchar(4)'
print #sql
--EXECUTE sp_executesql #sql, #params, #Flag, #symbol, #exchange, #limit, #chargerate, #ChgType, #IsActive, #Mkrid, #statecode
end
I am trying to create a stored procedure in which there will be as many conditions in WHERE clause as passed to the stored procedure. I hope I am clear about what I am trying to achieve. I am getting error Error converting data type varchar to numeric.
I think that a good solution would be this one
SELECT * from dbo.Clients
WHERE
(#param1 IS NULL OR field1 = #param1)
AND (#param2 IS NULL OR field2 = #param2)
With this approach the statement will not be re-processed (execution plan) by the server every time you execute the query.
What you could do is to rewrite your stored proc using dynamic SQL and include parts of where clause only if parameters are defined, e.g. replace the body with
declare #sql nvarchar(max)
set #sql = N'select * from Tbl_StampDutyException1 where 1 = 1'
if len(isnull(#exchange, '')) > 0
set #sql = #sql + N' and exchange = ' + cast(#exchange as nvarchar(100))
-- add all parameters; you need to cast them to nvarchar if they have other type
exec (#sql)
As an improvement, you can use sp_executesql to execute dynamic SQL. See here on how to use it. In this case, the code will be:
declare #sql nvarchar(max)
set #sql = N'select * from Tbl_StampDutyException1 where 1 = 1'
if len(isnull(#exchange, '')) > 0
set #sql = #sql + N' and exchange = #exchange'
-- add all parameters;
declare #params as nvarchar(max) = N'#Flag varchar(3),
#symbol varchar(13),
#exchange char(3),
#limit money,
#chargerate numeric(18,4),
#ChgType char(2),
#IsActive int,
#Mkrid varchar(11),
#statecode varchar(4)'
EXECUTE sp_executesql #sql, #params, #Flag, #symbol, #exchange, #limit, #chargerate, #ChgType, #IsActive, #Mkrid, #statecode
By the way, don't use select * in stored procedures, it's not a good practice. List all the columns you want to return. Otherwise, if the table definition changes, you will get different result to what it was previously.
What I guess you need is a CONDITIONAL WHERE CLAUSE approach, have provided the sample script below, you need to convert all the IF conditions to a CASE and you then you can combine all the conditions into a single SELECT statement:
SELECT * FROM Tbl_StampDutyException1
WHERE
exchange = CASE WHEN #exchange='' or #exchange is null THEN exchange ELSE #exchange END
AND symbol = Case when #symbol='' or #symbol is null THEN symbol ELSE symbol
AND *so on.....*