Conversion failed when converting the varchar(max) value 'TNK_99' to data type int - sql

I am working with MS SQL. I wrote a simple code which goes through columns in my table and find the columns with more than 30% zero value. I will save name of column with more than 30% zero in #array.#count just has number of columns and #column has name of all columns.
DECLARE #array varchar(MAX)
DECLARE #sql varchar(MAX),
#column as varchar(MAX)
SELECT #count = (SELECT COUNT(*) FROM sys.columns WHERE object_id =
OBJECT_ID('UVE305_TREND_2.dbo.LOGTNK'))
WHILE #counT>0
BEGIN
SET #column = (SELECT name FROM sys.columns WHERE object_id = OBJECT_ID('UVE305_TREND_2.dbo.LOGTNK') AND column_id = #count)
SELECT #column
SET #array = (SELECT COUNT(#column) FROM UVE305_TREND_2.dbo.LOGTNK WHERE
#column = 0 )
select #array
SET #count= #count- 1
END;
IF #r_count >= CAST(#array AS INT)
SET #list= #column+','+#list;
when I tried to run my query I got following error:
Conversion failed when converting the varchar(max) value 'TNK_99' to
data type int.
'TNK_99' is my column name.
any help will be appreciated.

This expression:
WHERE #column = 0
Is being converted to:
WHERE 'TNK_99' = 0
That is, it is comparing a string (which happens to be a column name) to a number. By the rules of SQL the values are converted to numbers -- and you get a conversion error.
There is no simple way to solve this. The solution involves dynamic SQL, which is rather more complex than your code.
EDIT:
The code looks like:
DECLARE #sql NVARCHAR(MAX);
WHILE #count > 0
BEGIN
SET #column = (SELECT name FROM sys.columns WHERE object_id = OBJECT_ID('UVE305_TREND_2.dbo.LOGTNK') AND column_id = #count);
SET #SQL = 'SELECT #array = COUNT(*) FROM UVE305_TREND_2.dbo.LOGTNK WHERE ' + QUOTENAME(#column) + ' = 0 )'
EXEC sp_executesql #SQL, N'#array int output', #array=#array output;
SELECT #column, #array
SET #count= #count- 1
END;
As with the original code, this assumes that all columns are numeric. This code is a little vague on what "zero value" means. Perhaps you intend:
SET #SQL = 'SELECT #array = COUNT(*) FROM UVE305_TREND_2.dbo.LOGTNK WHERE ' + QUOTENAME(#column) + ' = ''0'' )'

Related

Verify all columns can convert from varchar to float

I have tried a bunch of different ways like using cursors and dynamic SQL, but is there a fast way to verify that all columns in a given table can convert from varchar to float (without altering the table)?
I want to get a print out of which columns fail and which columns pass.
I am trying this method now but it is slow and cannot get the list of columns that pass or error out.
drop table users;
select *
into users_1
from users
declare #cols table (i int identity, colname varchar(100))
insert into #cols
select column_name
from information_schema.COLUMNS
where TABLE_NAME = 'users'
and COLUMN_NAME not in ('ID')
declare #i int, #maxi int
select #i = 1, #maxi = MAX(i) from #cols
declare #sql nvarchar(max)
while(#i <= #maxi)
begin
select #sql = 'alter table users_1 alter column ' + colname + ' float NULL'
from #cols
where i = #i
exec sp_executesql #sql
select #i = #i + 1
end
I found this code on one of the SQL tutorials sites.
Why all the drop/create/alter nonsense? If you just want to know if a column could be altered, why leave your table in a wacky state, where the columns that can be altered are altered, and the ones that can't just raise errors?
Here's one way to accomplish this with dynamic SQL (and with some protections):
DECLARE #tablename nvarchar(513) = N'dbo.YourTableName';
IF OBJECT_ID(#tablename) IS NOT NULL
BEGIN
DECLARE #sql nvarchar(max) = N'SELECT ',
#tmpl nvarchar(max) = N'[Can $colP$ be converted?]
= CASE WHEN EXISTS
(
SELECT 1 FROM ' + #tablename + N'
WHERE TRY_CONVERT(float, COALESCE($colQ$,N''0'')) IS NULL
)
THEN ''No, $colP$ cannot be coverted''
ELSE ''Yes, $colP$ CAN be converted'' END';
SELECT #sql += STRING_AGG(
REPLACE(REPLACE(#tmpl, N'$colQ$',
QUOTENAME(name)), N'$colP$', name), N',')
FROM sys.columns
WHERE object_id = OBJECT_ID(#tablename)
AND name <> N'ID';
EXEC sys.sp_executesql #sql;
END
Working db<>fiddle
This is never going to be "fast" - there is no great shortcut to having to read and validate every value in the table.

sql sever 2012 sum of dynamic columns

Assume I have a table with 50 columns with name AMT_0,AMT_1,..AMT_49. Is there possible sum of dynamic number of column depending on Variable.
example1: SELECT SUM(AMT_0,AMT_1,AMT_2,AMT_3) FROM TBL where the Variable is equal to 4.
example2: SELECT SUM(AMT_0,AMT_1,..,AMT_23) FROM TBL where the Variable is equal to 24.
Ideally, you should redesign your database, so that AMT is normalized into rows. Then the query is far simpler and does not require dynamic SQL.
The only way to do this as it stands is with dynamic SQL, you need to make sure to check all columns exists by looking them up in system tables, and quote all the column names properly:
DECLARE #sql nvarchar(max) = N'
SELECT SUM(
' +
(
SELECT STRING_AGG(QUOTENAME(c.name), N',')
FROM sys.columns c
WHERE c.object_id = OBJECT_ID(N'TBL')
AND c.name LIKE N'AMT_%'
) + N'
)
FROM TBL
';
EXEC (#sql)
You'll need to build some dynamic SQL. Something like this should do the trick
DECLARE #var smallint;
SELECT #var = 15; -- change variable value to control # of columns summed
DECLARE #sql varchar(4000);
DECLARE #cntr smallint; -- incremental counter variable for WHILE loop
SELECT #sql = '';
SELECT #cntr = 1;
WHILE #cntr > 0 AND #cntr <= 50 AND #cntr <= #var
BEGIN
IF #sql = ''
BEGIN
SELECT #sql = 'SELECT SUM(AMT_0';
END
ELSE
SQL #sql += ' + AMT_' + CONVERT(varchar(10), (#cntr-1));
END
SELECT #cntr += 1;
END
SELECT #sql += ') FROM TBL;';
EXEC (#sql);

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

Sum of blank values

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).

Get column names in SQL server that satisfy a where condition on data

I just had a random doubt while working with SQL-server to which i thought i could get it clarified here.
Say- i have a condition that i want to find out all the column names in the database which satisfy my where condition on data.
Example:-
There are some 20-30 tables in a SQL-Server DB.Now all i need is a query to find out the list of column names which have "Ritesh" as a data field in them.
I don't know if it is really possible in the first place.
I hope i am clear. Please, any help will be most appreciated.
Thank You.
Ritesh.
This should work, but be aware, this will take a while to execute in large databases. I have assumed that the search string might be just a part of the data contained and am using wildcards. I feel this is purely academic, as I am unable to imagine a scenario, where this will be required.
--you need to iterate the whole columns of entire table to find the matched record
--another thing is that you need dynamic sql to find the table name
DECLARE #Value varchar(50) --value for that find the column Name
SET #Value = 'Ritesh'
CREATE TABLE #Table
(
TableName Varchar(500),ColumnName Varchar(500),
Id int Identity(1,1) --use for iteration
)
CREATE TABLE #Results
(
TableName varchar(500),
ColumnName varchar(500)
)
INSERT INTO #Table
SELECT
TABLE_SCHEMA + '.' + TABLE_NAME AS TableNam,
Column_name AS ColumnName
FROM INFORMATION_SCHEMA.COLUMNS
WHERE Data_type IN ('char', 'nchar', 'varchar', 'nvarchar')
--change the datatype based on the datatype of sample data you provide
-- also remember to change the wildcard, if the input datatype is not a string
DECLARE #Count Int --total record to iterated
SET #Count = 0;
SELECT
#Count = COUNT(*)
FROM #Table
DECLARE #I int --initial value one to iterate
SET #I = 1;
DECLARE #TableName varchar(500)
SET #TableName = ''
DECLARE #ColumnName varchar(500)
SET #ColumnName = ''
DECLARE #Str nvarchar(1000)
SET #Str = ''
DECLARE #param nvarchar(1000)
SET #param = ''
DECLARE #TableNameFound varchar(max)
SET #TableNameFound = ''
DECLARE #Found bit
SET #Found = 0;
WHILE #I<=#Count
BEGIN
SET #Found = 0;
SELECT
#TableName = TableName,
#ColumnName = ColumnName
FROM #Table
WHERE Id = #I;
SET #param = '#TableName varchar(500),#ColumnName varchar(500),#Value varchar(50),#TableNameFound varchar(max),#Found bit output'
SET #str = 'Select #Found=1 From ' + #TableName + ' where ' + #ColumnName + ' Like ' + '''' + '%' + #Value + '%' + ''''
-- here we are using tablename and actual value to find in table
EXEC sp_executesql #str,
#param,
#TableName,
#ColumnName,
#Value,
#TableNameFound,
#Found OUTPUT
IF #Found=1
BEGIN
INSERT INTO #Results (TableName, ColumnName)
SELECT
#TableName,
#ColumnName
END
--increment value of #I
SET #I = #I + 1;
END
--Display Results
SELECT * FROM #Results
--Clean Up
DROP TABLE #Table
DROP TABLE #Results