Specific column -- Error converting data type nvarchar to bigint - tsql

This is part of the T-SQL.I am getting below error. Can anyone guide me.The issue is because of the value column which is of nvarchar datatype
SELECT RuleID, SourceID, DataFileID, ChildCount, DP_State
FROM
(SELECT DP_State.RuleID, CAST(DP_State.SourceID AS VARCHAR(20)) AS SourceID, CAST(DP_State.DataFileID AS VARCHAR(20)) AS DataFileID, ChildCount, DP_State
FROM (
SELECT RuleID ,
RuleResultID ,
CASE WHEN ISNUMERIC(ISNULL([ResultValue], 0)) = 1 THEN
CAST(ISNULL([Value], 0) AS BIGINT)
ELSE
-1
END AS ChildCount,
Error I am getting :

Try this if you are using SQL Server 2012 or later
SELECT RuleID,
SourceID,
DataFileID,
ChildCount,
DP_State
FROM (
SELECT DP_State.RuleID,
CAST(DP_State.SourceID AS VARCHAR(20)) AS SourceID,
CAST(DP_State.DataFileID AS VARCHAR(20)) AS DataFileID,
ChildCount,
DP_State
FROM (
SELECT RuleID,
RuleResultID,
CASE
WHEN TRY_CONVERT(INT, ISNULL([ResultValue],0)) IS NOT NULL
THEN CAST(ISNULL([Value], 0) AS BIGINT)
ELSE - 1
END AS ChildCount,
)
)

You are implicitly casting to an integer by first checking [value] against 0 in ISNULL(). Only after that you are casting to an integer, instead try the following:
Evaluate against a string:
CAST(ISNULL([Value], '0') AS BIGINT)
Or first cast to an integer:
ISNULL(CAST([Value] AS BIGINT), 0)

Related

DB2 select statement does not return any rows

I wrote query:
select * from tbl1 as tbl1
where tbl1.pkey >= cast(080138738 as varchar(10))
and tbl1.pkey <= cast(080138738 as var char(10);
tbl1 contains row that its pkey value is 08013878 but this query dosn't retutn any rows.
Ok, let's start guessing, if you don't want to provide some fully reproducible example.
select *
from
(
VALUES
-- doesn't return a row
'080138738'
-- returns a row
--'80138738'
) tbl1 (pkey)
where tbl1.pkey >= CAST (080138738 as varchar(10))
and tbl1.pkey <= CAST (080138738 as varchar(10))
If you have pkey of VARCHAR data type then look at the example above.
Let's look at the result of the CAST (080138738 as varchar(10)) expression.
The integer 080138738 value is equal to the 80138738 one without leading zero(es), and namely this value is converted to the '80138738' VARCHAR value.
But the following query returns no rows obviously:
SELECT 1
FROM SYSIBM.SYSDUMMY1
WHERE '080138738' >=
'80138738' -- the result of CAST (080138738 as varchar(10))
AND '080138738' <=
'80138738' -- the result of CAST (080138738 as varchar(10))
The solution is to use correct data type for parameters.
--# SET TERMINATOR #
CREATE TABLE TBL1 (PKEY VARCHAR (10))#
INSERT INTO TBL1 (PKEY) VALUES '080138738'#
BEGIN
DECLARE V_STMT VARCHAR (500);
DECLARE V_CNT INT;
DECLARE C1 CURSOR FOR S1;
SET V_STMT =
'SELECT COUNT (*) FROM TBL1 '
|| 'WHERE pkey >= cast(? as varchar(10)) and pkey <= cast(? as varchar(10))';
PREPARE S1 FROM V_STMT;
-- Correct - using VARCHAR constants
OPEN C1 USING '080138738', '080138738';
-- Wrong - using INT constants
-- OPEN C1 USING 080138738, 080138738;
FETCH C1 INTO V_CNT;
-- We throw an exception, if the result is unexpected
IF V_CNT <> 1 THEN
SIGNAL SQLSTATE '75000' SET MESSAGE_TEXT = 'Not expected result';
END IF;
END
#
dbfiddle link

Creating an index for a complex search query

Having trouble determining how to create an index to support a complex query. I've only ever used indexes in basic scenarios, so I'm at a loss for how to approach this with far more complex ones.
Here's the SP being used which will help identify the types and columns being used:
CREATE OR REPLACE FUNCTION "SearchListings" (
"#MakeID" UUID,
"#ModelID" UUID,
"#TrimID" UUID,
"#MinYear" INTEGER,
"#MaxYear" INTEGER,
"#MinMileage" INTEGER,
"#MaxMileage" INTEGER,
"#MinPrice" FLOAT,
"#MaxPrice" FLOAT,
"#Colours" JSONB,
"#Keywords" JSONB,
"#Distance" FLOAT,
"#Region" VARCHAR(50),
"#Longitude" FLOAT,
"#Latitude" FLOAT,
"#MaxMMR" FLOAT,
"#SellerType" VARCHAR(50),
"#Transmission" VARCHAR(50),
"#TimeRange" VARCHAR(25)
)
RETURNS TABLE (
"ID" UUID
) AS
$func$
BEGIN
RETURN QUERY SELECT
li."ID"
FROM
"Listings" AS li
WHERE
"Status" = 'ACTIVE' AND
"MakeID" = "#MakeID" AND
"ModelID" = "#ModelID" AND
(
"#TrimID" IS NULL OR
li."TrimID" = "#TrimID"
) AND
(
"#MinYear" IS NULL OR
li."Year" > "#MinYear"
) AND
(
"#MaxYear" IS NULL OR
li."Year" < "#MaxYear"
) AND
(
"#MinMileage" IS NULL OR
li."Mileage" > "#MinMileage"
) AND
(
"#MaxMileage" IS NULL OR
li."Mileage" < "#MaxMileage"
) AND
(
"#MinPrice" IS NULL OR
"Price" > "#MinPrice"
) AND
(
"#MaxPrice" IS NULL OR
li."Price" < "#MaxPrice"
) AND
(
"#Colours" IS NULL OR
(
"#Colours" IS NOT NULL OR
"#Colours" ?& ARRAY["Colour"]
)
) AND
(
"#Keywords" IS NULL OR
(
"#Keywords" IS NOT NULL AND
"#Keywords" ?& ARRAY(
SELECT * FROM JSONB_ARRAY_ELEMENTS(li."Keywords"::JSONB)
)::TEXT[]
)
) AND
(
"#MaxMMR" IS NULL OR
li."MMR" < "#MaxMMR"
) AND
(
"#Transmission" IS NULL OR
"#Transmission" = 'AUTOMATIC_MANUAL' OR
li."Transmission" = "#Transmission"
) AND
(
"#SellerType" IS NULL OR
"#SellerType" = 'PRIVATE_DEALER' OR
li."SellerType" = "#SellerType"
) AND
(
CASE
WHEN "#TimeRange" = 'LAST_TWO_NEWER' THEN
li."PublishedAt" >= (CURRENT_DATE - INTERVAL '2 days')
WHEN "#TimeRange" = 'ONLY_NEW' THEN
li."PublishedAt" >= (CURRENT_DATE - INTERVAL '30 minutes')
ELSE TRUE
END
) AND
(
"#Longitude" IS NULL OR
"#Latitude" IS NULL OR
"#Distance" IS NULL OR
ST_DWithin(
ST_SetSRID(ST_MakePoint("#Longitude", "#Latitude"), 4326),
ST_SetSRID(li."Location", 4326),
"#Distance"
)
);
END;
$func$ LANGUAGE PLPGSQL;
Should I be creating an index that includes all the different columns in one? That would however exclude some of the most specialised indexing types such as JSONB's GIN indexes which I have set as well as the GIST spatial index for "Location".
So in essence the question becomes, how would I create a compound index (if it exists) to maximize my query performance?
Aside from that can you suggest a tutorial or go-to guide for designing indexes? There's lots of resources out there but they're relatively confusing or poorly written.

How AND expressions are evaluated?

I have the following situation:
DECLARE #DataSource TABLE
(
[ID] BIGINT
)
INSERT INTO #DataSource ([ID])
VALUES (1)
,(2)
,(3)
DECLARE #IDForSearch VARCHAR(4) = 'TEXT'
If we try to extract record using our wrong type parameter:
SELECT IIF( EXISTS( SELECT 1 FROM #DataSource WHERE [ID] = #IDForSearch), 'Found', 'Missing')
we are getting the error below:
Msg 8114, Level 16, State 5, Line 14
Error converting data type varchar to bigint.
But If I add a simple isNumeric check everything is working fine:
SELECT IIF( ISNUMERIC(#IDForSearch) = 1 AND EXISTS( SELECT 1 FROM #DataSource WHERE [ID] = #IDForSearch), 'Found', 'Missing')
I firstly thought that the first part of the expression is executed:
ISNUMERIC(#IDForSearch) = 1
and because it fails, the second one is not executed and the error is not thrown.
But, if I change the expressions places everything is working again:
SELECT IIF( EXISTS( SELECT 1 FROM #DataSource WHERE [ID] = #IDForSearch) AND ISNUMERIC(#IDForSearch) = 1, 'Found', 'Missing')
Why there is no error in these situations?
I think that there is some internal cast (I speak about SQL 212), because:
select IIF( 1='a','Found','Missing')
results in
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the varchar value 'a' to data type int.
and
select IIF(isnumeric('a')=1 and 1='a','Found','Missing')
returns
Missing

in T-SQL, is it possible to find names of columns containing NULL in a given row (without knowing all column names)?

Is it possible in T-SQL to write a proper query reflecting this pseudo-code:
SELECT {primary_key}, {column_name}
FROM {table}
WHERE {any column_name value} is NULL
i.e. without referencing each column-name explicitly.
Sounds simple enough but I've searched pretty extensively and found nothing.
You have to use dynamic sql to solve that problem. I have demonstrated how it could be done.
With this sql you can pick a table and check the row with id = 1 for columns being null and primary keys. I included a test table at the bottom of the script. Code will not display anything if there is not primary keys and no columns being null.
DECLARE #table_name VARCHAR(20)
DECLARE #chosencolumn VARCHAR(20)
DECLARE #sqlstring VARCHAR(MAX)
DECLARE #sqlstring2 varchar(100)
DECLARE #text VARCHAR(8000)
DECLARE #t TABLE (col1 VARCHAR(30), dummy INT)
SET #table_name = 'test_table' -- replace with your tablename if you want
SET #chosencolumn = 'ID=1' -- replace with criteria for selected row
SELECT #sqlstring = COALESCE(#sqlstring, '') + 'UNION ALL SELECT '',''''NULL '''' '' + '''+t1.column_name+''', 1000 ordinal_position FROM ['+#table_name+'] WHERE [' +t1.column_name+ '] is null and ' +#chosencolumn+ ' '
FROM INFORMATION_SCHEMA.COLUMNS t1
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE t2
ON t1.column_name = t2.column_name
AND t1.table_name = t2.table_name
AND t1.table_schema = t2.table_schema
WHERE t1.table_name = #table_name
AND t2.column_name is null
SET #sqlstring = stuff('UNION ALL SELECT '',''''PRIMARY KEY'''' ''+ column_name + '' '' col1, ordinal_position
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE table_name = ''' + #table_name+ '''' + #sqlstring, 1, 10, '') + 'order by 2'
INSERT #t
EXEC( #sqlstring)
SELECT #text = COALESCE(#text, '') + col1
FROM #t
SET #sqlstring2 ='select '+stuff(#text,1,1,'')
EXEC( #sqlstring2)
Result:
id host_id date col1
PRIMARY KEY PRIMARY KEY PRIMARY KEY NULL
Test table
CREATE TABLE [dbo].[test_table](
[id] int not null,
[host_id] [int] NOT NULL,
[date] [datetime] NOT NULL,
[col1] [varchar](20) NULL,
[col2] [varchar](20) NULL,
CONSTRAINT [PK_test_table] PRIMARY KEY CLUSTERED
(
[id] ASC,
[host_id] ASC,
[date] ASC
))
Test data
INSERT test_table VALUES (1, 1, getdate(), null, 'somevalue')

t-sql : Error converting data type varchar to numeric in then statement

I cannot understand the error because I'm not trying to convert to numeric the variable #FQTROQ.
declare #FQTROQ varchar(30)
declare #FQNUTQ decimal(6,0)
set #FQTROQ = 'R-354'
set #FQNUTQ = 100
SELECT ( CASE WHEN (#FQTROQ is not null and #FQTROQ <> '')
THEN ( #FQTROQ )
ELSE ( #FQNUTQ ) END ) AS Numero_Troquel
Any help? thanks
declare #FQTROQ varchar(30)
declare #FQNUTQ decimal(6,0)
set #FQTROQ = 'R-354'
set #FQNUTQ = 100
SELECT CASE WHEN (#FQTROQ is not null and #FQTROQ <> '')
THEN #FQTROQ
ELSE CAST(#FQNUTQ AS VARCHAR(30)) END AS Numero_Troquel
You need to cast the DECIMAL as a VARCHAR so that the output from the CASE statement have the same output value.
You need to do this:
SELECT ( CASE WHEN (#FQTROQ is not null and #FQTROQ <> '')
THEN ( #FQTROQ )
ELSE ( CAST(#FQNUTQ AS VARCHAR(30))) END ) AS Numero_Troquel
because the returned value from a column needs to match, SQL Server will try to convert your VARCHAR to a NUMERIC, not the other way around, which is what you probably want.
What's with that naming convention, btw?
It's because you have 2 variables of different types, and even though you're only trying to return ONE of those values as "Numero_Troquel", they have to be compatible types. What it's doing is trying to convert the #FQTROQ variable into a DECIMAL.
You'd either need to do:
SELECT ( CASE WHEN (#FQTROQ is not null and #FQTROQ <> '')
THEN ( #FQTROQ )
ELSE ( CAST(#FQNUTQ AS VARCHAR(30)) ) END ) AS Numero_Troquel
OR...
IF (#FQTROQ is not null and #FQTROQ <> '')
SELECT #FQTROQ AS Numero_Troquel -- this will return as a VARCHAR
ELSE
SELECT #FQNUTQ AS Numero_Troquel -- this will return as a DECIMAL