SQL counter flag is not filtered - sql

I'm using SQL developer and I'm getting an error I don't fully understand.
Due to data privacy, I cannot share the real query, but the question is fairly simple.
I have a query to obtain table T (which works if ran alone) and I want to filter a Y/N flag so I have the following query:
select * from T where flag ='Y'
While this query works, I want the observations which do not fullfil the condition but neither of the following queries works:
select * from T where flag <>'Y'
select * from T where flag ='N'
*I get the following error:
01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
Action: Specify a valid number .
Vendor code 1722
I tried to export the table to analyze it on another language, but I still get the same error.
Can anyone help?

As you confirmed T in your example is not a table, your error simply seems to be caused by a conversion error somewhere on 1 or several records WHERE flag <> 'Y'. This is why the query works with flag = 'Y' but not with your other conditions.
Minimal case to reproduce would be something like:
CREATE TABLE MyTable (
Field VARCHAR(10),
Flag VARCHAR(1)
);
CREATE VIEW T AS SELECT to_number(Field), Flag FROM MyTable;
INSERT INTO MyTable VALUES ('1', 'Y'); /* OK */
INSERT INTO MyTable VALUES ('No way', 'N'); /* Fails */
In your case, the error may not be caused by a call to to_number but this is the best clue I can give given the limited information you provide. It might not be a call to a function at all but the result of a calculation using operators only.
You simply need to make sure the fields can be converted/used in a calculation before you actually attempt to do so (CASE WHEN ... THEN ... ELSE NULL for instance).

Related

Case expression to check if column exists throws invalid column name error

I'm building a Stored Procedure meant to be run daily. Due to how the data is provided me, some days some of the columns necessary for the output are not in the file that's imported to a temporary table.
For the output, the value can be null/empty, but the actual column has to be there.
I've tried the following code:
select
case
when exists(
select * from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'tableName' and COLUMN_NAME = 'ABC'
) then ABC
else ''
end
as 'XYZ' from tableName
I know for a fact that in the tests I'm running the column DOES NOT exist, so I'm expecting the SELECT statment to simply return an empty string for column XYZ.
However when running such SELECT statement, I get the following error:
Invalid column name 'ABC'.
Since I know from the start that the column ABC does not exist, I was expecting that the EXISTS(...) would evaluate to FALSE and jump straight to the ELSE statement. However it seems that the column name is still evaluated.
How can I get around this?
I believe i have solved my troubles thanks to the workaround provided by #MartinSmith
(https://dba.stackexchange.com/questions/66741/why-cant-i-use-a-case-statement-to-see-if-a-column-exists-and-not-select-from-i/66755#66755)
I ended up using an alternative version of the workaround provided, linked by the poster of #MartinSmith's solution, but the results seem to be what i was expecting.
Regarding the Only one expression can be specified in the select list when the subquery is not introduced with EXISTS error, it was being caused by me trying to SELECT two columns in the subquery. Solution came from here: https://stackoverflow.com/a/7684626/18191554
Now, my code is as follows:
select
.
.
.
.
(select (SELECT [ABC]
from dbo.tableName
where ID = temp.ID])
from (select '' as [ABC]) as dummy)
as 'XYZ',
.
.
.
from tableName
where ABC is the column that may or may not exist.
Thanks to everyone involved

ORA-00936: missing expression for dynamic data

I have 2 queries, which takes data dynamically.
Select cid from table1 where cNumber={{custNbr}}
Here {{custNbr}} comes from a .txt file.
update table2 set status='A' where customer_id=NVL({{cid}},0000)
Here {{customer_id}} comes from output of step 1.
Issue: When step 1 returns NULL, it actually returns an empty string ''. As a result, Step 2 translates to -
update table2 set status='A' where customer_id=NVL(,0000)
This throws an error java.sql.SQLSyntaxErrorException: ORA-00936: missing expression
How do I rewrite the queries to make them work.
In your case, it's probably sufficient to provide a fallback for the result of the first query:
Select nvl(cid, -1) as cid
from table1
where cNumber={{custNbr}}
This assumes that -1 does not appear as a customer ID in table2. Therefore, the UPDATE will be syntactically valid, but it will update zero rows.
CAVEAT
However, I'd be strongly suspicious of a tool that cannot handle NULL values as input to Database queries. You might want to contact the DevTest support regarding this.

sql ORA-00900: Invalid SQL statement

please help
IF EXISTS(SELECT * FROM MERC_ADM_VERSION )then UPDATE MERC_ADM_VERSION SET
VER_VALEUR = 20150409 WHERE VER_CLE = 'MEAD' ELSE INSERT INTO MERC_ADM_VERSION
('VER_VALEUR', 'VER_CLE') VALUES (20150409, 'MEAD');
ORA-00900: Invalid SQL statement
Remove the single quotes from the columns in the insert statement.
Instead of
('VER_VALEUR', 'VER_CLE')
It should be
(VER_VALEUR, VER_CLE)
Your question is quite unclear as to what you are trying to do. However, my best interpretation is you are looking for an oracle merge statement. Below is an example based on assumptions I made on the little information you provided. You are most likely looking for a MERGE statement. This allows you to perform a single operation that can either update or insert based on your criteria.
Also, you appear to be using a date, but in number format. I did nothing to address this due to lack of any table definition. You may still have problems with it.
MERGE
INTO merc_adm_version TARGET -- The table you want to update/insert into
USING (SELECT 20150409 as ver_valeur, 'MEAD' as ver_cle FROM dual) SOURCE -- The source of the data
ON (TARGET.ver_cle = SOURCE.ver_cle) -- How to try and match records between source and target
WHEN MATCHED THEN UPDATE SET ver_valeur = 20150409 -- When there is a match, how to update
WHEN NOT MATCHED THEN INSERT (ver_cle, ver_valeur) -- When there is not a match, how to insert
VALUES ('MEAD', 20150409);

Why does SQL evaluate statements in the true section of an if exists construct, even if the `if exists` returns false?

(I apologize in advance for the awful explanation, but if you run the queries below you should see what I mean!)
Why does MSSQL evaluate statements in the true section of an if exists construct, even if the if exists returns false, causing errors?
For example, in the two queries below, the first checks if a table exists (which it does) and also checks if that table has certain columns. For some reason, running this query throws the following errors because the table exists but the columns don't.
Msg 207, Level 16, State 1, Line 21
Invalid column name 'colB'.
Msg 207, Level 16, State 1, Line 21
Invalid column name 'colC'.
Msg 207, Level 16, State 1, Line 21
Invalid column name 'colA'.
The behavior I expected here was for SQL to just move onto the falsepart of the construct, without throwing errors. (As it does with the next query).
However, the second script (which is identical, bar table names) executes successfully. This is because the table the query is searching for does not exist.
--Scripts to setup the example.
CREATE DATABASE TEST
GO
USE TEST
GO
CREATE TABLE t1 (colD VARCHAR(255)) --Create a table with the correct name, but incorrect column names.
GO
--This query fails, because t1 exists, even though the columns in t1 don't.
IF EXISTS (select * from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1' AND COLUMN_NAME IN ('colA','colB','colC'))
BEGIN
SELECT colA FROM t1 WHERE colB = 0 AND colC = 1
END
ELSE BEGIN
SELECT 'FALSE'
END
GO
--This query executes ok, because t2 does not exist.
IF EXISTS (select * from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't2' AND COLUMN_NAME IN ('colA','colB','colC'))
BEGIN
SELECT colA FROM t2 WHERE colB = 0 AND colC = 1
END
ELSE BEGIN
SELECT 'FALSE'
END
Is anybody able to explain to me why the first query errors, when the second query runs fine?
So far, I've only managed to test this in Microsoft SQL Server 2012.
To answer the first part of this question. Assuming familiarity with a language (such as C#) which has some form of runtime type inspection (e.g. Reflection).
Assume you have code like this:
SomeType t = GetSomeTypeFromSomewhere();
if(t.GetType().GetMethod("FunTimes")!=null)
{
t.FunTimes();
}
And assume that SomeType doesn't contain a public method called FunTimes. Even though I've written a guard around trying to invoke the FunTimes method, I get an error. And, specifically, I get a compile time error - the C# compiler cannot even generate the code, let alone get close to running the code, obtaining the result from GetMethod() and deciding not to run the code within the nested block.
To switch back to your code, the exact same type of analysis applies here:
IF EXISTS (select * from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1' AND COLUMN_NAME IN ('colA','colB','colC'))
BEGIN
SELECT colA FROM t1 WHERE colB = 0 AND colC = 1
END
ELSE BEGIN
SELECT 'FALSE'
END
SQL Server tries to compile this batch and fails. It never executes the code, so it never gets to the point of deciding which branch (IF or ELSE) to take.
So, if all of the above is true, why then does the second piece of code work? That's because of an particular feature of T-SQL called Deferred Name Resolution. Basically, there's a special rule that applies when the object that's missing is a table (or view, since the two are indistinguishable until the object can be found). In that specific instance, SQL Server will not immediately signal a compilation error.
Under deferred name resolution, execution will start and, if something causes schema changes (such as by adding the missing table/view), this causes the system to recompile the remainder of the code.
I think you are evaluating the results wrong (AND it is not your fault IMHO).
EXISTS part returns FALSE in both cases. However, the SQL query parser is funny, it parses the inside expressions and gives the error before execution of the statements, only if column(s) is missing, it doesn't give an error if the table is missing.
In your first query where it seems to be evaluating to TRUE, try changing table name to something like t2 and you would see it runs and evaluates to FALSE in both.

SQL error "ORA-01722: invalid number"

A very easy one for someone,
The following insert is giving me the
ORA-01722: invalid number
why?
INSERT INTO CUSTOMER VALUES (1,'MALADY','Claire','27 Smith St Caulfield','0419 853 694');
INSERT INTO CUSTOMER VALUES (2,'GIBSON','Jake','27 Smith St Caulfield','0415 713 598');
INSERT INTO CUSTOMER VALUES (3,'LUU','Barry','5 Jones St Malvern','0413 591 341');
INSERT INTO CUSTOMER VALUES (4,'JONES','Michael','7 Smith St Caulfield','0419 853 694');
INSERT INTO CUSTOMER VALUES (5,'MALADY','Betty','27 Smith St Knox','0418 418 347');
An ORA-01722 error occurs when an attempt is made to convert a character string into a number, and the string cannot be converted into a number.
Without seeing your table definition, it looks like you're trying to convert the numeric sequence at the end of your values list to a number, and the spaces that delimit it are throwing this error. But based on the information you've given us, it could be happening on any field (other than the first one).
Suppose tel_number is defined as NUMBER - then the blank spaces in this provided value cannot be converted into a number:
create table telephone_number (tel_number number);
insert into telephone_number values ('0419 853 694');
The above gives you a
ORA-01722: invalid number
Here's one way to solve it. Remove non-numeric characters then cast it as a number.
cast(regexp_replace('0419 853 694', '[^0-9]+', '') as number)
Well it also can be :
SELECT t.col1, t.col2, ('test' + t.col3) as test_col3
FROM table t;
where for concatenation in oracle is used the operator || not +.
In this case you get : ORA-01722: invalid number ...
This is because:
You executed an SQL statement that tried to convert a string to a
number, but it was unsuccessful.
As explained in:
Oracle/PLSQL: ORA-01722 Error.
To resolve this error:
Only numeric fields or character fields that contain numeric values
can be used in arithmetic operations. Make sure that all expressions
evaluate to numbers.
As this error comes when you are trying to insert non-numeric value into a numeric column in db it seems that your last field might be numeric and you are trying to send it as a string in database. check your last value.
Oracle does automatic String2number conversion, for String column values! However, for the textual comparisons in SQL, the input must be delimited as a String explicitly: The opposite conversion number2String is not performed automatically, not on the SQL-query level.
I had this query:
select max(acc_num) from ACCOUNTS where acc_num between 1001000 and 1001999;
That one presented a problem: Error: ORA-01722: invalid number
I have just surrounded the "numerical" values, to make them 'Strings', just making them explicitly delimited:
select max(acc_num) from ACCOUNTS where acc_num between '1001000' and '1001999';
...and voilĂ : It returns the expected result.
edit:
And indeed: the col acc_num in my table is defined as String. Although not numerical, the invalid number was reported. And the explicit delimiting of the string-numbers resolved the problem.
On the other hand, Oracle can treat Strings as numbers. So the numerical operations/functions can be applied on the Strings, and these queries work:
select max(string_column) from TABLE;
select string_column from TABLE where string_column between '2' and 'z';
select string_column from TABLE where string_column > '1';
select string_column from TABLE where string_column <= 'b';
In my case the conversion error was in functional based index, that I had created for the table.
The data being inserted was OK. It took me a while to figure out that the actual error came from the buggy index.
Would be nice, if Oracle could have gave more precise error message in this case.
If you do an insert into...select * from...statement, it's easy to get the 'Invalid Number' error as well.
Let's say you have a table called FUND_ACCOUNT that has two columns:
AID_YEAR char(4)
OFFICE_ID char(5)
And let's say that you want to modify the OFFICE_ID to be numeric, but that there are existing rows in the table, and even worse, some of those rows have an OFFICE_ID value of ' ' (blank). In Oracle, you can't modify the datatype of a column if the table has data, and it requires a little trickery to convert a ' ' to a 0. So here's how to do it:
Create a duplicate table: CREATE TABLE FUND_ACCOUNT2 AS SELECT * FROM FUND_ACCOUNT;
Delete all the rows from the original table: DELETE FROM FUND_ACCOUNT;
Once there's no data in the original table, alter the data type of its OFFICE_ID column: ALTER TABLE FUND_ACCOUNT MODIFY (OFFICE_ID number);
But then here's the tricky part. Because some rows contain blank OFFICE_ID values, if you do a simple INSERT INTO FUND_ACCOUNT SELECT * FROM FUND_ACCOUNT2, you'll get the "ORA-01722 Invalid Number" error. In order to convert the ' ' (blank) OFFICE_IDs into 0's, your insert statement will have to look like this:
INSERT INTO FUND_ACCOUNT (AID_YEAR, OFFICE_ID) SELECT AID_YEAR, decode(OFFICE_ID,' ',0,OFFICE_ID) FROM FUND_ACCOUNT2;
I have found that the order of your SQL statement parameters is also important and the order they are instantiated in your code, this worked in my case when using "Oracle Data Provider for .NET, Managed Driver".
var sql = "INSERT INTO table (param1, param2) VALUES (:param1, :param2)";
...
cmd.Parameters.Add(new OracleParameter("param2", Convert.ToInt32("100")));
cmd.Parameters.Add(new OracleParameter("param1", "alpha")); // This should be instantiated above param1.
Param1 was alpha and param2 was numeric, hence the "ORA-01722: invalid number" error message. Although the names clearly shows which parameter it is in the instantiation, the order is important. Make sure you instantiate in the order the SQL is defined.
For me this error was a bit complicated issue.
I was passing a collection of numbers (type t_numbers is table of number index by pls_integer;) to a stored procedure. In the stored proc there was a bug where numbers in this collection were compared to a varchar column
select ... where ... (exists (select null from table (i_coll) ic where ic.column_value = varchar_column))
Oracle should see that ic.column_value is integer so shouldn't be compared directly to varchar but it didn't (or there is trust for conversion routines).
Further complication is that the stored proc has debugging output, but this error came up before sp was executed (no debug output at all).
Furthermore, collections [<empty>] and [0] didn't give the error, but for example [1] errored out.
The ORA-01722 error is pretty straightforward. According to Tom Kyte:
We've attempted to either explicity or implicity convert a character string to a number and it is failing.
However, where the problem is is often not apparent at first. This page helped me to troubleshoot, find, and fix my problem. Hint: look for places where you are explicitly or implicitly converting a string to a number. (I had NVL(number_field, 'string') in my code.)
This happened to me too, but the problem was actually different: file encoding.
The file was correct, but the file encoding was wrong. It was generated by the export utility of SQL Server and I saved it as Unicode.
The file itself looked good in the text editor, but when I opened the *.bad file that the SQL*loader generated with the rejected lines, I saw it had bad characters between every original character. Then I though about the encoding.
I opened the original file with Notepad++ and converted it to ANSI, and everything loaded properly.
In my case it was an end of line problem, I fixed it with dos2unix command.
In my case I was trying to Execute below query, which caused the above error ( Note : cus_id is a NUMBER type column)
select *
from customer a
where a.cus_id IN ('115,116')
As a solution to the caused error, below code fragment(regex) can be used which is added in side IN clause (This is not memory consuming as well)
select *
from customer a
where a.cus_id IN (select regexp_substr (
com_value,
'[^,]+',
1,
level
) value
from (SELECT '115,116' com_value
FROM dual)rws
connect by level <=
length ( com_value ) - length ( replace ( com_value, ',' ) ) + 1)
try this as well, when you have a invalid number error
In this
a.emplid is number and b.emplid is an varchar2 so if you got to convert one of the sides
where to_char(a.emplid)=b.emplid
You can always use TO_NUMBER() function in order to remove this error.This can be included as INSERT INTO employees phone_number values(TO_NUMBER('0419 853 694');