ORA-01427: single-row subquery returns more than one row Update SQL Query - oracle

I am trying to update column where find duplicate CNICNO and update column. But I am getting following error
ORA-01427: single-row subquery returns more than one row
When I query to find duplicate CNICNO records against HOFID then show 5 duplicate records
Duplicate Records Query:
SELECT hofid
FROM hof
WHERE cnicno IN (SELECT cnic_no FROM we_group_hof_k)
Records:
[1]: https://i.stack.imgur.com/ltC1m.png
In table "WE_GROUP_HOF_K" column "GROUP_ID" null records. I want "HOFID" records update with "GROUP_ID" column.
SQL QUERY:
UPDATE we_group_hof_k
SET group_id = (SELECT cnicno
FROM hof
WHERE cnicno IN (SELECT cnic_no FROM we_group_hof_k));
How to solve this problem?

Unless I'm wrong, shouldn't UPDATE actually look like this?
UPDATE we_group_hof_k w
SET w.GROUP_ID =
(SELECT h.cnicno
FROM hof h
WHERE h.cnicno = w.cnic_no);
Instead of IN, join appropriate columns form the table to be updated (we_group_hof_k) with the data source table (hof).

The error message pretty much nails the problem - your subquery:
SELECT cnicno
FROM hof
WHERE cnicno IN (SELECT cnic_no FROM we_group_hof_k)
returns multiple rows. But UPDATE needs a single value, so you have to ensure that your subquery returns only a single row. You need to ensure that your subquery never returns multiple rows (you can use an aggregate function like MAX() but you have to ensure that fits your business needs).

Related

Select max query returning all the rows in a table in Apache Hive

I am querying my data using this query
SELECT date_col,max(rate) FROM crypto group by date_col ;
I am expecting a single row but it is returning all the rows in the table. What is the mistake in this query?
You'll get one row per date_col because you're grouping by it. If you just want the maximum rate then just do SELECT max(rate) FROM crypto;.
If you want to get the date_col for that record too then:
SELECT
date_col,
rate
FROM crypto
WHERE rate = (SELECT MAX(rate) FROM crypto)

Query to check the full schema scan for tables in Oracle DB

Hi I have a requirement to scan through the schema and identify the tables which are redundant (candidate for dropping) ,so i did a select in DBA_Dependencies to check whether the tables are being used in any of the DB object types like (Procedure, package body, views, Materialized views....) i was able to find some tables and excluded the tables ,since i also need to capture the total counts, when the table was last loaded/used is there a automated way to select only selected tables (not found in dependencies list) and capture the counts and also when it was used/loaded
Difficulty - so many tables 500+
i have used the below query
Query 1
select table_name,
to_number(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) c from '||owner||'.'||table_name)),'/ROWSET/ROW/C')) as count
from all_tables
where owner = 'SCHEMA_NAME'
Query 2
select owner, table_name, num_rows, sample_size, last_analyzed from all_tables;
Query 1 Result
Filter Table_name=CUST_ORDER
OWNER TABLE_NAME COUNT SAMPLE_SIZE LAST_ANALYZED
ABCD CUST_ORDER 1083 1023 01.01.2020
Query 2 Result
Filter Table_name=CUST_ORDER
OWNER TABLE_NAME NUM_ROWS SAMPLE_SIZE LAST_ANALYZED
ABCD CUST_ORDER 1023 1023 01.01.2020
Question
Query 1 - Results not matching when compared with query 2 ,since the same table and filter is applied
in both the queries and why the results are not matching ?
but when i randomly checked other filter it is matching , does any one know the reason ?
Upon further testing i encountered an error ,what does this error signify permissions ?
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-04040: file **-**.csv in ****_***_***_***** not found
29913. 00000 - "error in executing %s callout"
*Cause: The execution of the specified callout caused an error.
*Action: Examine the error messages take appropriate action.
The number you see on all_tables is a point in time capture of the number of rows. It will only be updated if the statistics are rebuilt for that table.
Here is an example:
CREATE TABLE t1 AS
SELECT *
FROM all_objects;
SELECT t.num_rows
FROM all_tables t
WHERE t.table_name = 'T1';
-- 78570
SELECT COUNT(*)
FROM t1;
-- 78570
The stats and the physical number of rows match!
INSERT INTO t1
SELECT *
FROM all_objects ao
WHERE rownum <= 5;
-- 5 rows inserted
SELECT t.num_rows
FROM all_tables t
WHERE t.table_name = 'T1';
-- 78570
SELECT COUNT(*)
FROM t1;
-- 78575
Here we have the mis-match because rows were inserted (or maybe even deleted), but the stats for the table have not been updated. Let's update them:
BEGIN
dbms_stats.gather_table_stats(ownname => 'SCHEMA',
tabname => 'T1');
END;
/
SELECT t.num_rows
FROM all_tables t
WHERE t.table_name = 'T1';
-- 78575
Now you can see the rows match. Using the value from all_tables may be good enough for your research (and will certainly be faster to query than counting every table).
Query - 1 is actual data of the table and hence it is accurate data. One can rely on this query's output.
Query - 2 is not actual data. It is the data captured when table was last analyzed and one should not be dependant on this query for finding number of records in the table.
You can gather the stats on this table and execute the query-2 then you will find the same data as query-1
If records are not inserted or deleted from the table after stats are gathered, then query-1 and query-2 data will match for that table.

PL/SQL create function with param for a check constraint

Given the syntax:
CREATE [OR REPLACE] FUNCTION [Owner.]FunctionName
[(arguments [IN|OUT|IN OUT][NOCOPY] DataType [DEFAULT expr][,...])]
RETURN DataType [InvokerRightsClause] [DETERMINISTIC]
{IS|AS}
I think my query is syntactically correct, but for some reason, I get these errors during compilation:
Error(6,5): PL/SQL: SQL Statement ignored
Error(8,34): PL/SQL: ORA-00942: table or view does not exist
CREATE or replace FUNCTION aCombinationMismatches(p_column1 IN VARCHAR2)
RETURN Number
IS
duplicate_count NUMBER(4,0);
BEGIN
select count(*) into duplicate_count
from schema1.tableA a
inner join schema1.tableB b
on a.b_id = b.id and a.column1 = p_column1
group by a.b_id, a.column1, a.column2, b.column1, b.column2, b.column3;
return duplicate_count;
END;
Anyone see anything wrong with my query above?
Also I'd like to how to set this UDF up to be used to create a CHECK constraint. How exactly do I specify the param: p_param1 to the function assuming this is the value of a field column1 in a row that a user is trying to insert? I just don't want the user to insert a record into tableA that consists of duplicate combinations of fields across tables: tableA and tableB.
Note: The tables tableA and tableB do exist - a select query like below indicates it. So the error above is rather confusing to me, I must add. (All table and column names in the two queries were found/replaced with dummy values.)
select count(*)
from schema1.tableA a
inner join schema1.tableB b
on a.b_id = b.id
group by a.b_id, a.column1, a.column2, b.column1, b.column2, b.column3;
Output:
Count(*)
OK, you already know that you have problem with priviliges. I wanted to add that you won't be able to create CHECK constraint basing on your function. According to documentation:
The condition of a check constraint can refer to any column in the table, but it cannot refer to columns of other tables.
Conditions of check constraints cannot contain the following constructs:
Subqueries and scalar subquery expressions
Calls to the functions that are not deterministic (CURRENT_DATE, CURRENT_TIMESTAMP, DBTIMEZONE, LOCALTIMESTAMP, SESSIONTIMEZONE, SYSDATE, SYSTIMESTAMP, UID, USER, and USERENV)
Calls to user-defined functions
So to achieve what you want, you would have to define some triggers, or make use of some combination of MATERIALIZED VIEW and CHECK constraint. See for example this discussion on Ask Tom
You probably have access to TableA and TableB through a Role. This means that you can query the table, but you cannot create a procedure that reads or writes that table. In order to compile your procedure you should at least grant select on the table to your user.
In the link below you'll find more info
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1065832643319

Something is wrong in my oracle trigger

I need help in one of my Oracle Trigger syntax
CREATE OR REPLACE TRIGGER "TRG_TRIGGER" AFTER INSERT
ON T_TABLE
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
INSERT INTO T_TABLE_TEST
(DOC_ID , DOC_NAME)
VALUES
(:NEW.DOC_ID, SELECT DOC_NAME FROM OTHER_TABLE WHERE DOC_ID=DOC_ID);
Need DOC_NAME from other table. I think only my select query needs to be modified?
As others have suggested, you could rewrite the insert...values statement to be an insert...as select statement, and that would make the most sense.
Just fyi, there are two problems with your original insert statement that leap out at me:
You specified doc_id = doc_id in your select statement, whereas I think you meant doc_id = :new.doc_id. Your query would return all rows from the other table, and you'd get ORA-01427: single-row subquery returns more than one row, if your query was able to run.
You didn't enclose the select statement within brackets. It should be:
--
INSERT INTO T_TABLE_TEST
(DOC_ID , DOC_NAME)
VALUES
(:NEW.DOC_ID, (SELECT DOC_NAME FROM OTHER_TABLE WHERE DOC_ID=:NEW.DOC_ID));
The insert must be like this:
INSERT INTO T_TABLE_TEST
(DOC_ID , DOC_NAME)
SELECT :NEW.DOC_ID, DOC_NAME FROM OTHER_TABLE where doc_id = :NEW.DOC_ID;
Just a note, you can skip REFERENCING NEW AS NEW OLD AS OLD since OLD and NEW are defaults.
You need to specify which doc_name to select, so I think you are missing a where clause.. try this:
INSERT INTO T_TABLE_TEST
(DOC_ID , DOC_NAME)
SELECT t.doc_id, t.DOC_NAME FROM OTHER_TABLE t where t.doc_id = :NEW.DOC_ID;
Of course I guessed that other table have column named doc_id, change it to the relation column.

Oracle: Selecting * and aggregate column

Is it possible to select fields using the method below?
SELECT *, count(FIELD) FROM TABLE GROUP BY TABLE
I get the following error
ORA-00923: FROM keyword not found where expected
00923. 00000 - "FROM keyword not found where expected"
*Cause:
*Action:
Error at Line: 1 Column: 9
Is it a syntax error or do you have to explicitly define each column rather than using *?
You can't use * and other columns. If you use an alias, then you can:
SELECT t.*
, count(FIELD)
FROM TABLE t
Also, your GROUP BY TABLE is wrong. You can't group by the table name, you must specify some columns, like this:
SELECT t.customer
, count(FIELD)
FROM TABLE t
GROUP BY t.customer
The columns that are selected in the field should be
an expression used as one of the group by criteria , or
an aggregate function , or
a literal value
For this, you need to indicate the fields you needed and should fit in the following criteria mentioned above.
SELECT FIELD1,FIELD2, COUNT(*) FROM TABLE1 GROUP BY FIELD1, FIELD2
If you insist to use the logic of your query, the use of subquery should be helpful.
For example,
SELECT * FROM TABLE1 T1 INNER JOIN (SELECT FIELD1, COUNT(FIELD1) AS [CountOfFIELD1] FROM TABLE1 T2 GROUP BY FIELD1)T3 ON T1.FIELD1=T3.FIELD1
Instead of * you need to give the column names:
SELECT a, b, COUNT(FIELD)
FROM TABLE
GROUP BY a, b;

Resources