Oracle: Selecting * and aggregate column - oracle

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;

Related

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

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).

How to only select existing values from oracle?

I have a table with a massive number of columns. So many, that when I do SELECT * I can't even see any values because all the columns fill up the screen. I'd like to do something like this:
SELECT * FROM my_table WHERE NAME LIKE '%unique name%' AND <THIS COLUMN> IS NOT NULL
Is this possible? Note: VALUE is not a column.
There are so many questions on SO that ask this same question, but they have some bizarre twist, and the actual question is not answered.
I've tried:
SELECT * FROM my_table WHERE NAME LIKE '%unique name%' AND VALUE NOT NULL
*
Invalid relational operator
SELECT * FROM my_table WHERE NAME LIKE '%unique name%' AND VALUE <> ''
*
'VALUE': invalid identifier
SELECT * FROM my_table WHERE NAME LIKE '%unique name%' AND COLUMN NOT NULL
*
Missing Expression
Bonus Questions:
Is there any way to force Oracle to only show one output screen at a time?
Is there a variable to use in the WHERE clause that relates to the current column? Such as: WHERE this.column = '1', where it would check each column to match that expression?
Is there any way to get back your last command in Oracle? (I have to remote into a Linux box running Oracle - it's all command line - can't even copy/paste, so I have to type every command by hand, with a wonky connection, so it's taking an extremely long time to debug this stuff)
If you are trying to find all the non null column values for a particular record you could try an unpivot provided all the columns you are unpivoting have the same data type:
SELECT *
FROM (select * from my_table where name like '%unique value%')
UNPIVOT [include nulls] (col_value FOR col_name IN (col1, col2, ..., coln))
with the above code null values will be excluded unless you include the optional include nulls statement, also you will need to explicitly list each column you want unpivoted.
If they don't all have the same data type, you can use a variation that doesn't necessarily prune away all the null values:
select *
from (select * from my_table where name like '%unique value%')
unpivot ((str_val, num_val, date_val)
for col_name in ((cola, col1, date1)
,(colb, col2, date2)
,(colc, col3, date1)));
You can have a fairly large set of column groups, though here I'm showing just three, one for each major data type, with the IN list you need to have a column listed for each column in your column group, though you can reuse columns as shown by the date_val column where I've used date1 twice. As an alternative to reusing an existing column, you could use a dummy column with a null value:
select *
from (select t1.*, null dummy from my_table t1 where name like '%unique value%')
unpivot ((str_val, num_val, date_val)
for col_name in ((dummy, col1, date1)
,(colb, dummy, date2)
,(colc, col3, dummy)));
Have tried this?
SELECT * FROM my_table WHERE NAME LIKE '%unique name%' AND value IS NOT NULL;
Oracle / PLSQL: IS NOT NULL Condition
For row number:
SELECT field1, field2, ROW_NUMBER() OVER (PARTITION BY unique_field) R WHERE R=1;
Usually in Linux consoles you can use arrow up&down to repeat the last sentence.

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

Can i use the column in order by clasue

I have specifiec requirement .Actually this is my query. here amount is a column in my table.but i did not mention the amount column in select statement.here can i use this column in oreder by clause.
SELECT stud_name, stud_roll, stud_prg
FROM programcl
ORDER BY 3, amount, 1;
Yes, you can mix both positional and named assignments in your ORDER BY clause.
The positional assignments must appear in your SELECT list. The named assignments do not have to.
can i use this column in oreder by clause.
Yes of course you can use a different column in order by clause that wasn't selected from your select statement.
For example
select col1 from tab1
order by col2;
by this way you get results from col1 which will be displayed on order of col2.
Its Worth trying

Oracle insert if not exists statement

insert into OPT (email, campaign_id) values('mom#cox.net',100)
where not exists( select * from OPT where (email ="mom#cox.net" and campaign_id =100)) ;
Error report: SQL Error: ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
*Cause:
*Action:
how to insert a new row if it doesn't exists in Oracle?
insert into OPT (email, campaign_id)
select 'mom#cox.net',100
from dual
where not exists(select *
from OPT
where (email ='mom#cox.net' and campaign_id =100));
The correct way to insert something (in Oracle) based on another record already existing is by using the MERGE statement.
Please note that this question has already been answered here on SO:
oracle insert if row not exists
insert if not exists oracle
MERGE INTO OPT
USING
(SELECT 1 "one" FROM dual)
ON
(OPT.email= 'mom#cox.net' and OPT.campaign_id= 100)
WHEN NOT matched THEN
INSERT (email, campaign_id)
VALUES ('mom#cox.net',100)
;
insert into OPT (email, campaign_id)
select 'mom#coxnet' as email, 100 as campaign_id from dual MINUS
select email, campaign_id from OPT;
If there is already a record with mom#cox.net/100 in OPT, the MINUS will subtract this record from the select 'mom#coxnet' as email, 100 as campaign_id from dual record and nothing will be inserted. On the other hand, if there is no such record, the MINUS does not subract anything and the values mom#coxnet/100 will be inserted.
As p.marino has already pointed out, merge is probably the better (and more correct) solution for your problem as it is specifically designed to solve your task.
Another approach would be to leverage the INSERT ALL syntax from oracle,
INSERT ALL
INTO table1(email, campaign_id) VALUES (email, campaign_id)
WITH source_data AS
(SELECT 'mom#cox.net' email,100 campaign_id
FROM dual
UNION ALL
SELECT 'dad#cox.com' email,200 campaign_id
FROM dual)
SELECT email
,campaign_id
FROM source_data src
WHERE NOT EXISTS (SELECT 1
FROM table1 dest
WHERE src.email = dest.email
AND src.campaign_id = dest.campaign_id);
INSERT ALL also allow us to perform a conditional insert into multiple tables based on a sub query as source.
There are some really clean and nice examples are there to refer.
oracletutorial.com
oracle-base.com/

Resources