Invalid number while comparing string to number oracle - sql

Hello I am currently involved in a project that is running for over 2 years, and yesterday, we started to face following issue:
One query that was always used and ran at least 20.000 every single day, yesterday fom nothing started to return invalid number error.
ORA-01722: invalid number
select orq.rt_id, orec.* from orderrec orec
join order_header oh on (oh.order_code = orec.ordernumber and oh.page = orec.pagenumber)
left join order_request orq on oh.orq_id = orq.orq_id
where ordernumber=? and pagenumber=? and state < 100
the problematic part is:
oh.order_code = orec.ordernumber
order_code is a string
ordernumber is a number
As this is would give a high impact on clients production I've change the equal comparison to a like find query bellow. After this change process started to work again without issue.
select orq.rt_id, orec.* from orderrec orec join order_header oh on (oh.order_code like orec.ordernumber and oh.page = orec.pagenumber) left join order_request orq on oh.orq_id = orq.orq_id
where ordernumber=? and pagenumber=? and state < 10
This query is a XML file used with a java program.
My doubt is why this would have happend?

I would check to see if the ORDER_CODE field, which you say is a string, contains any new values with non-digit characters (0-9) as that would be my guess as to the cause.
Even though your ORDER_CODE field is a string, when you join that field with a number field, Oracle will attempt to convert that string to a number (implicitly). You might as well be using the to_number() function on the ORDER_CODE field, because that is how it's actually being processed.
For instance, this query:
select *
from tablea a
join tableb b
on a.order_code = b.ordernumber
Will not return an error if ORDER_CODE contains values with only digits (0-9) and no letters.
But if it does contain at least one such value, boom, you get the error you describe.
It is true that you can use LIKE to avoid the error, but it will be unable to match rows where the ORDER_CODE has letters. Notice how in this example http://sqlfiddle.com/#!4/f00f91/1/0 '9A' won't match with 9, whereas '8' does match with 8.
The answer in a nutshell is that because you're joining two fields of a different format, one a string, one a number, a conversion from the string to a number is implied. And obviously, when the string contains letters such as A, B, C, etc. it will be unable to do the conversion and so it will give you that error.
You can run this query to find the "problem values", my guess is that whatever rows are returned were recently inserted, causing the error:
Fiddle:
http://sqlfiddle.com/#!4/f5b55/1/0
select *
from order_header
where regexp_like(order_code, '[^0-9]')

Related

Multiply values ​of two variables according to id

I have a problem with the multiplication of two variables.
I have two sql statements with which I get the number of hours that an employee has worked during a specific month, and another statement to get the hourly cost that each employee has.
I must say that they are two different tables in the database.
What I would like is to multiply the hours of each employee by the hourly cost that employee has, and then add the results.
These two sentences work fine, if I do "print_r" I see the results that each employee has.
I guess I have to do it through the ID, but I don't know how to do it.
This is what I have so far, and I only get it to multiply the first person it finds.
$SumaHoras = $DB->Sql ("SELECT Id_Persona, CONCAT(SUM(Horas)* 3600)/36000000 as Hora FROM table1");
$SumaCosteHora = $DB->Sql("SELECT Id_CostPers, CONCAT(Coste_Hora) as Coste FROM table2");
$suma1 = [];
while($totalSumaHoras = $DB->Row($SumaHoras)){
$suma1 = $totalSumaHoras;
print_r($suma1);
}
$suma2 = [];
while($totalSumaCoste = $DB->Row($SumaCosteHora)){
$suma2 = $totalSumaCoste;
print_r($suma2);
}
$total4 = $suma1->Hora * $suma2->Coste;
I don't know if I explained myself well, but I appreciate any help you can offer me.
Your first line of code does not work - it generates errors - "The concat function requires 2 to 254 arguments." and then if you remove the CONCAT you get "Column 'table1.Id_Persona' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause." - as pointed out by #isamu
You should not use CONCAT for numbers - that returns a string - always use the correct Type for data.
To get all the information you require at once you need to use a JOIN see This article
E.g.
SELECT Id_Persona, t2.Coste_Hora * (SUM(t1.Horas) * 3600.0)/36000000.0
FROM table1 t1
INNER JOIN table2 t2 ON t1.Id_Persona = t2.Id_CostPers
group by Id_Persona, t2.Coste_Hora
I'm not sure why you are using that particular calculation but note I have appended .0 to those integer values to ensure that decimal calculation takes place - to explain what I mean try running these two lines of SQL
SELECT 10 * 3600/36000000;
SELECT 10 * 3600.0/36000000.0;

ORA-01427: single-row subquery returns more than one row - on simple query

The following simple SQL query generates an ORA-01427 error when searching for certain specific object numbers.
SELECT OBJ
FROM A.TABLEA
WHERE (OBJ ='XXXXXX');
The query works fine except for when you choose an OBJ where there is another OBJ row/s with a corresponding A suffix 'XXXXXXA'.
i.e. querying for OBJ = 'XXXXXXA' works fine, but querying for OBJ = 'XXXXXX' produces the error, alternatively querying for OBJ = 'XXXXXY' works fine when there is no corresponding OBJ = 'XXXXXYA'
Is there a way to handle / avoid the error where it will pick the first/last/random single row?
And going a step further instead of searching for specific Objects I want to search within a date range where I have to join another table to get the date, the error will show if there is a 'XXXXXX' with corresponding 'XXXXXXA' within the date range. See code below,
SELECT
t1.*,
t2.OBJ,
t2.DATE
FROM
A.TABLEA t1
LEFT OUTER JOIN
A.TABLEB t2
ON (t1.OBJ = t2.OBJ)
WHERE
(t2.DATE BETWEEN TO_DATE ('2019/04/01', 'yyyy/mm/dd')
AND TO_DATE ('2019/04/30', 'yyyy/mm/dd');
Is there a way to handle / avoid the error in this code to force it to select 1 row?
Thanks in advance.
I was able to solve this situation by selecting the correct data tables that had the base data (rather than the sql generated table I was originally selecting) and performing the join on the first 12 characters of the object number,
(SUBSTR(t1.OBJ,1,12) = SUBSTR(t2.OBJ,1,12)
where the 13 character had the extra A suffix.
Thanks for your help.

How to resolve a Left Join sub-query error?

In MS-Access I'm trying to join three tables. The third table is created from a sub-query designed to aggregate dates because I don't want multiple records per day when aligned with the first table.
When I entered the left join sub-query, I got this error:
The field is too small to accept the amount of data you attempted to
add. Try inserting or pasting less data.
I've run the sub-query separately and it returns about 19,000 records. Which is quite smaller than the actual table. If I use the actual table, the query works just fine, but it includes the duplicate records when there is more than one entry per day on the third table.
SELECT
SUM([ACD Calls]),
(SUM([Avg ACD Time]*[ACD Calls])/SUM([ACD Calls]))/86400,
(SUM([Avg ACW Time]*[ACD Calls])/SUM([ACD Calls]))/86400,
((SUM([Hold Time])/SUM([ACD Calls])))/86400,
((SUM([Avg ACD Time]*[ACD Calls])
+ SUM([Avg ACW Time]*[ACD Calls]))/SUM([ACD Calls]))/86400,
SUM([Time Adhering])/SUM([Total Time Scheduled]),
SUM([SS])/SUM([SO])
FROM
(
(
[GroupSumDaily]
LEFT JOIN Adherence_WKLY ON (GroupSumDaily.[Day] = Adherence_WKLY.[Day])
AND (GroupSumDaily.Agent = Adherence_WKLY.Agent)
)
LEFT JOIN
(
SELECT Evaluation_List.[Agent],
Evaluation_List.Recording_Date,
SUM(Evaluation_List.[Score]) as SS,
SUM(Evaluation_List.[Out of]) as SO
From Evaluation_List
Group By Evaluation_List.[Recording_Date],
Evaluation_list.[Agent]
)
as Evals ON (GroupSumDaily.[Day] = Evals.[Recording_Date])
AND (GroupSumDaily.Agent = Evals.Agent)
)
WHERE
(
[GroupSumDaily].[Agent] = "LastName FirstName"
AND Month([GroupSumDaily].[Day]) =1
AND Year([GroupSumDaily].[Day]) =2018
AND [GroupSumDaily].[Day] > #2/23/2015#
)
It looks like you don't have a "main" table to query from.
I'd try removing the first two open brackets after the FROM statement (and their equivalent closing brackets.)
If that doesn't fix it, try moving the whole sub-query into a separate query and selecting from the results...
It turns out the subquery fields are automatically limited to 50 characters and this was the root of the problem. When I limited the return to LEFT([Agent], 50), the error disappeared. Is there a way to set character length is a subquery field?
The other odd things is, none of my fields were actually over 50 characters... when I ran Select [Agent] Where LEN([Agent]) >= 50, it returned only 1 records, and it was the "NEW" blank record from the bottom. I confirmed that it completely blank, with no spaces or tabs. Very confusing.

SQL query malfunction

So Im trying to use INNER JOIN in my sql command because I am trying to replace the Foreign keys ID numbers with the text value of each column. However, when I use INNER JOIN, the column for "Standards" always gives me the same value. The following is what I started with
SELECT Grade_Id, Cluster_Eng_Id, Domain_Math_Eng_Id, Standard
FROM `math_standards_eng`
WHERE 1
and returns this (which is good). Notice the value of Standard values are different
Grade_Id Cluster_Eng_Id Domain_Math_Eng_Id Standard
103 131 107 Explain equivalence of fractions in special cases...
104 143 105 Know relative sizes of measurement units within o...
When I try to use Inner Join, the values for Grade_Id, Cluster_Eng_Id, and Domain_Math_Eng_Id are changed from numbers to actual text. Standard column values, however, seems to return the same value. Here is my code:
SELECT
grades_eng.Grade, domain_math_eng.Domain, cluster_eng.Cluster,
math_standards_eng.Standard
FROM
math_standards_eng
INNER JOIN
grades_eng ON math_standards_eng.Grade_Id = grades_eng.Id
INNER JOIN
domain_math_eng ON math_standards_eng.Domain_Math_Eng_Id
INNER JOIN
cluster_eng ON math_standards_eng.Cluster_Eng_Id
This is what I get when I run the query:
Grade Domain Cluster Standard
3rd Counting and cardinality Know number names and the count sequence Explain equivalence of fractions in special cases...
3rd Expressions and Equations Know number names and the count sequence Explain equivalence of fractions in special cases...
3rd Functions Know number names and the count sequence Explain equivalence of fractions in special cases.
4th Counting and cardinality Know number names and the count sequence Know relative sizes of measurement units within o...
4th Expressions and Equations Know number names and the count sequence Know relative sizes of measurement units within o...
The text value for Standard keeps on showing the same value per grade and I do not know why. 3rd Will keep showing the same thing, and then the next grade will change to a new value and repeat over and over. Lastly, each table has a 1:M relationship with standard as they each appear multiple times in the standard Table. Any advice would be greatly appreciated.
You are missing the = part of your INNER JOIN on domain_math_eng and cluster_eng. I would expect something like:
SELECT grades_eng.Grade, domain_math_eng.Domain, cluster_eng.Cluster, math_standards_eng.Standard FROM math_standards_eng
INNER JOIN grades_eng ON math_standards_eng.Grade_Id = grades_eng.Id
INNER JOIN domain_math_eng ON math_standards_eng.Domain_Math_Eng_Id = domain_math_eng.Id
INNER JOIN cluster_eng ON math_standards_eng.Cluster_Eng_Id = cluster_eng.Id

Update table with combined field from other tables

I have a table with actions that are being due in the future. I have a second table that holds all the cases, including the due date of the case. And I have a third table that holds numbers.
The problems is as follows. Our system automatically populates our table with future actions. For some clients however, we need to change these dates. I wanted to create an update query for this, and have this run through our scheduler. However, I am kind of stuck at the moment.
What I have on code so far is this:
UPDATE proxima_gestion p
SET fecha = (SELECT To_char(d.f_ult_vencim + c.hrem01, 'yyyyMMdd')
FROM deuda d,
c4u_activity_dates c,
proxima_gestion p
WHERE d.codigo_cliente = c.codigo_cliente
AND p.n_expediente = d.n_expediente
AND d.saldo > 1000
AND p.tipo_gestion_id = 914
AND p.codigo_oficina = 33
AND d.f_ult_vencim > sysdate)
WHERE EXISTS (SELECT *
FROM proxima_gestion p,
deuda d
WHERE p.n_expediente = d.n_expediente
AND d.saldo > 1000
AND p.tipo_gestion_id = 914
AND p.codigo_oficina = 33
AND d.f_ult_vencim > sysdate)
The field fecha is the current action date. Unfortunately, this is saved as a char instead of date. That is why I need to convert the date back to a char. F_ult_vencim is the due date, and hrem01 is the number of days the actions should be placed away from the due date. (for example, this could be 10, making the new date 10 days after the due date)
Apart from that, there are a few more criteria when we need to change the date (certain creditors, certain departments, only for future cases and starting from a certain amount, only for a certain action type.)
However, when I try and run this query, I get the error message
ORA-01427: single-row subquery returns more than one row
If I run both subqueries seperately, I get 2 results from both. What I am trying to accomplish, is that it connects these 2 queries, and updates the field to the new value. This value will be different for every case, as every due date will be different.
Is this even possible? And if so, how?
You're getting the error because the first SELECT is returning more than one row for each row in the table being updated.
The first thing I see is that the alias for the table in UPDATE is the same as the alias in both SELECTs (p). So all of the references to p in the subqueries are referencing proxima_gestion in the subquery rather than the outer query. That is, the subquery is not dependent on the outer query, which is required for an UPDATE.
Try removing "proxima_gestion p" from FROM in both subqueries. The references to p, then, will be to the outer UPDATE query.