I've the following code with regards to inserting and checking values into the teradata database.My point is that data that is read from the flat file whose value after trimming leading 0 is 0 or NULL should not be loaded and if otherwise, the value should be loaded into the target table.......
VALUES
(
CASE STUD_ID WHEN TRIM(LEADING '0' FROM :STUD_ID) NOT IN ('0', NULL) THEN TRIM(LEADING '0' FROM :STUD_ID)
ELSE NEXT
END,
:B,
:C
)
I've unsure of if the next statement does exist for teradata in the conditioning statement...I've got this error
Illegal expression in WHEN clause of CASE expression.
Statement# 1, Info =0
I tried with the select statement in the VALUES area,
VALUES
(
SELECT (CASE STUD_ID WHEN TRIM(LEADING '0' FROM :STUD_ID) != '0' THEN TRIM(LEADING '0' FROM :STUD_ID)
ELSE 1000
END )
FROM :STUD_ID,
:B,
:C
)
I got this error statement...
Syntax error, expected something like ')' between '(' and
the 'SELECT' keyword.
The CASE ... WHEN syntax expects a single value for comparison (i.e. CASE some_expression WHEN 1 THEN 'Y'). Try the CASE WHEN ... form instead:
CASE
WHEN TRIM(LEADING '0' FROM :STUD_ID) NOT IN ('0', NULL)
THEN TRIM(LEADING '0' FROM :STUD_ID)
ELSE NEXT
END
You can also do this:
COALESCE(NULLIF(TRIM(LEADING '0' FROM :STUD_ID),0),NEXT) -- Return "NEXT" if 0 or NULL
There are several issues, ravioli fixed the syntax.
But your logic is flawed, too: TRIM(LEADING '0' FROM :STUD_ID) NOT IN ('0', NULL) will never be true because after trimming zeroes you never get '0' and additionally any cpmparison to NULL yields unknown. CASE WHEN TRIM(LEADING '0' FROM :STUD_ID) = '' OR :STUD_ID IS NULL THEN fixes this.
But based on your previous question you want to skip this row and this is not possible in BTEQ. Either switch to a load utility/TPT (preferred if it's a larger number of rows) or load the data as is in a staging table and apply the filter when INSERT/SELECTing into the target.
Related
I'm seeing some unexpected behavior when querying with a where clause on a coalesced char field in an Oracle database.
It seems that the results of
CASE WHEN COALESCE(char_field, 'some_val') = 'someOtherVal'
are different than the results of
CASE WHEN char_field = 'someOtherVal'
The specific comparisons in which I've noticed this weird output are 'between', 'in', and 'equals'. These are the weird outputs I'm seeing:
Between seems to be non-inclusive on the upper end
In and equals return false for every comparison
Here's some sql to replicate the weirdness:
CREATE TABLE delete_me( some_char CHAR(8) );
INSERT ALL
INTO delete_me (some_char) VALUES ('1')
INTO delete_me (some_char) VALUES ('2')
INTO delete_me (some_char) VALUES ('4')
INTO delete_me (some_char) VALUES ('5')
INTO delete_me (some_char) VALUES ('abc1')
INTO delete_me (some_char) VALUES (null)
SELECT 1 FROM DUAL;
SELECT some_char,
COALESCE(some_char, 'wasNull') AS coalesce_some_char,
CASE
WHEN (some_char BETWEEN '1' AND '5')
THEN 'true'
ELSE 'false'
END AS between_1_5,
CASE
WHEN (COALESCE(some_char, 'wasNull') BETWEEN '1' AND '5')
THEN 'true'
ELSE 'false'
END AS coalesce_between_1_5,
CASE
WHEN (some_char IN ('1', '5'))
THEN 'true'
ELSE 'false'
END AS in_1_5,
CASE
WHEN (COALESCE(some_char, 'wasNull') IN ('1', '5'))
THEN 'true'
ELSE 'false'
END AS coalesce_in_1_5,
CASE
WHEN (some_char = 'abc1')
THEN 'true'
ELSE 'false'
END AS equals_abc1,
CASE
WHEN (COALESCE(some_char, 'wasNull') = 'abc1')
THEN 'true'
ELSE 'false'
END AS coalesce_equals_abc1
FROM delete_me;
I would have expected the output of the comparisons on coalesced fields to match those on non-coalesced fields for all operators except IS NULL.
Does anyone have any idea why these results wouldn't match up?
Your problem is in the data type of some_char. When a column of type CHAR is compared to a string, Oracle blank pads the string to the length of the column (see the docs). In the tests you are doing, the values match in length ('1' vs '1') or are completely different ('1' vs 'abc1') so everything works fine. However when you use COALESCE on a CHAR field, the output of COALESCE is the fully blank padded column value returned as a VARCHAR (see the docs for NVL) and so the comparison string is not blank padded, and you are then comparing '1 ' vs '1', which fails. There are a couple of ways to work around this. You can TRIM the output of COALESCE i.e.
TRIM(COALESCE(some_char, 'wasNull'))
or change the data type of some_char to VARCHAR(8) instead.
I've made a demo of all of this on dbfiddle
Here's my query where I'm testing my case structure:
SELECT TOP 1 CASE 130
WHEN '000000000000000' THEN '0'
WHEN '' THEN '0'
WHEN 'XXX' THEN '0'
WHEN 'RETIRED' THEN '0'
WHEN 'STUDENT' THEN '0'
ELSE '1'
END AS employed_flag
INTO #employedbeta
FROM CreditBureau.Experian
I'm just trying to make a new temporary table, but I'd like my case to work first. I keep getting the error:
Conversion failed when converting the varchar value 'XXX' to data type int.
In the database, the column 130 is a char, and I don't know why it thinks I want to make it a number. SQL server management studio, if it matters.
The column name is 130, I left the '1' off because I rewrote it here but I get the error regardless in my actual query.
130 is an integer literal. If that's really the column name, you'll have to escape it using double quotes. As a side note, you should probably return the same type (char) in the else branch too:
CASE "130"
WHEN '000000000000000' THEN '0'
WHEN '' THEN '0'
WHEN 'XXX' THEN '0'
WHEN 'RETIRED' THEN '0'
WHEN 'STUDENT' THEN '0'
ELSE '1'
END AS employed_flag
130 is a really bad column name. But, I would simplify the logic to:
SELECT TOP 1 (CASE WHEN [130] IN ('000000000000000', '', 'XXX', 'RETIRED', 'STUDENT')
THEN 0 ELSE 1
END) AS employed_flag
INTO #employedbeta
FROM CreditBureau.Experian;
Note that I also changed the employed_flag to a numeric value rather than a string. That makes more sense to me.
I need to filter out rows in table where numer_lini column has number in it and it is between 100 and 999, below code works just fine when i comment out line where i cast marsnr to integer. However when i try to use it i get error: Invalid character found in a character string argument of the function "INTEGER". when looking at the list seems like replace and translate filters only numbers just fine and select only contains legit numbers (list of unique values is not long so its easy to scan by eye). So why does it fail to cast something? I also tried using integer(marsnr), but it produces the same error. I need casting because i need numeric range, otherwise i get results like 7,80 and so on. As I mentioned Im using IBM DB2 database.
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where numer_lini in (
select marsnr
from (
select
distinct numer_lini marsnr
from alaska.trasa
where case
when replace(translate(numer_lini, '0','123456789','0'),'0','') = ''
then numer_lini
else 'no'
end <> 'no'
)
where cast(marsnr as integer) between 100 and 999
)
fetch first 300 rows only
If you look at the optimized SQL from the Db2 explain, you will see that Db2 has collapsed your code into a single select.
SELECT DISTINCT Q2.NUMER_LINI AS "NUMER_LINI",
Q2.WAR_TRASY AS "WAR_TRASY",
Q2.ID_PRZ1 AS "ID_PRZ1",
Q2.ID_PRZ2 AS "ID_PRZ2",
Q1.NUMER_LINI
FROM ALASKA.TRASA AS Q1,
ALASKA.TRASA AS Q2
WHERE (Q2.NUMER_LINI = Q1.NUMER_LINI)
AND (100 <= INTEGER(Q1.NUMER_LINI))
AND (INTEGER(Q1.NUMER_LINI) <= 999)
AND (CASE WHEN (REPLACE(TRANSLATE(Q1.NUMER_LINI,
'0',
'123456789',
'0'),
'0',
'') = '') THEN Q1.NUMER_LINI
ELSE 'no' END <> 'no')
Use a CASE to force Db2 to do the "is integer" check first. Also, you don't check for the empty string.
E.g. with this table and data
create TABLE alaska.trasa (numer_lini VARCHAR(10), war_trasy INT , id_prz1 INT, id_prz2 INT);
insert into alaska.trasa values ('',1,1,1),('99',1,1,1),('500',1,1,1),('3000',1,1,1),('00300',1,1,1),('AXS',1,1,1);
This SQL works
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where case when translate(numer_lini, '','0123456789') = ''
and numer_lini <> ''
then integer(numer_lini) else 0 end
between 100 and 999
Although that does fail if there is an embedded space in the input. E.g. '30 0'. To cater for that, a regular expressing is probably preferred. E.g.
select numer_lini, war_trasy, id_prz1, id_prz2
from alaska.trasa
where case when regexp_like(numer_lini, '^\s*[+-]?\s*((\d+\.?\d*)|(\d*\.?\d+))\s*$'))
then integer(numer_lini) else 0 end
between 100 and 999
In sqlserver, I write a query in that i use "case" but it is giving error, this is my case.
(case when sm.SegCode =0 then '' else sm.SegCode = 7 end)
please help me.
Thanks for all for giving response, actually I have a parameter #id. Now I want to check when it is not zero I check that condition sm.segcode else if #id is zero then I don't want to check the condition that is sm.segcode = #id.
There are two issues with the statement you showed:
the syntactic error of else sm.SegCode = 7
the attempted mixing of types with the empty string and the int
Try this instead:
case when sm.SegCode = 0 then '' else '7' end
Of course that is partially a guess, because I'm not sure exactly what you are trying to achieve by setting the result to either an empty string or the integer 7.
this would be syntactically correct:
case sm.SegCode when '0' then '' else '7' end
or
case sm.SegCode when 0 then NULL else 7 end
if that columns allows NULL's that is
you can see more about case when in the documentation: http://msdn.microsoft.com/en-us/library/ms181765.aspx
Always try to return Same DATA TYPE value from Case statement, seems your first condistion returns VARCHAR whereas the else section returns INT, it's not possible, so best to convert each value to VARCHAR, so 7 will be '7' in else statement, thanks
(CASE
WHEN sm.SegCode = 0 THEN ''
ELSE '7' END)
SQL Syntax is still something I am learning. I am getting the error noted below the this snippet of code.
SELECT
CASE WHEN LTRIM(RTRIM(cLehmanNo)) =' ' THEN NULL
WHEN cLehmanNo IS NOT NULL THEN REPLACE ( cLehmanNo,SUBSTRING (cLehmanNo,PATINDEX( '%[^a-zA-Z0-9 '''''']%',cLehmanNo),1), ' ' )
END asLOAN_NUMBER
,CASE WHEN LTRIM(RTRIM(cMERS)) =' ' THEN NULL
WHEN cMERS IS NOT NULL THEN REPLACE ( cMERS,SUBSTRING (cMERS,PATINDEX( '%[^a-zA-Z0-9 '''''']%',cMERS),1), ' ' )
END asMERS_ID
and 100+ more of same.
Msg 8133, Level 16, State 1, Line 1
None of the result expressions in a CASE specification can be NULL.
What am I doing wrong? How do I keep the gist of the statement and not get this crazy error?
This happens when it can't infer the type.
e.g.
SELECT CASE WHEN 1 = 2 THEN NULL ELSE NULL END
But this works
SELECT CASE WHEN 1 = 2 THEN NULL ELSE replace(NULL,'','') END
so I doubt the error is from the code you have shown us (You are using string functions and the following quick test shows that it will assume that to be varchar(8000))
SELECT CASE WHEN 1 = 2 THEN NULL ELSE REPLACE(NULL,'','') END a
INTO t /*Creates column of datatype varchar(8000)*/
You need to convert NULL to a correct type matching the overall values, e.g. CONVERT(VARCHAR(10), NULL), otherwise the server can't deduce which type to make the resulting value.
The error message actually means that all results in one of your case expressions are null. You have an expression like:
case when something then null when something then null end
At least one of the results has to be something other than null. You could circumvent this, but most likely there is a mistake in the query, as a case exression that always returns the same result is pointless.
The error message has been changed to:
At least one of the result expressions
in a CASE specification must be an
expression other than the NULL
constant.
SELECT
CASE WHEN LTRIM(RTRIM(cLehmanNo)) =' ' THEN NULL
WHEN cLehmanNo IS NOT NULL THEN REPLACE ( cLehmanNo,SUBSTRING (cLehmanNo,PATINDEX( '%[^a-zA-Z0-9 '''''']%',cLehmanNo),1), ' ' )
ELSE ''
END asLOAN_NUMBER
,CASE WHEN LTRIM(RTRIM(cMERS)) =' ' THEN NULL
WHEN cMERS IS NOT NULL THEN REPLACE ( cMERS,SUBSTRING (cMERS,PATINDEX( '%[^a-zA-Z0-9 '''''']%',cMERS),1), ' ' )
ELSE ''
END asMERS_ID