How to debug "ORA-00911: invalid character" in this SQL Query? - sql

I tried to run the following query on Toad for Oracle. And it gives the error "ORA-00911: invalid character". Can someone please help me to figure out the issue?
DELETE FROM `CC_AUDIT_TRAIL`
WHERE SEQ_NO NOT IN (
SELECT SEQ_NO
FROM (
SELECT SEQ_NO
FROM `CC_AUDIT_TRAIL`
ORDER BY SEQ_NO DESC
LIMIT 1000
) foo
);

You have written a MySQL query. Perhaps you want this:
DELETE FROM CC_AUDIT_TRAIL
WHERE SEQ_NO NOT IN (SELECT SEQ_NO
FROM (SELECT SEQ_NO
FROM CC_AUDIT_TRAIL
ORDER BY SEQ_NO DESC
) foo
WHERE rownum <= 1000
);

Couple of observations:
To Aleksej's point, quotes around the table name are not necessary
You are sending direct query to Oracle, so semi-colon (;) is probably not needed
If above two point don't fix your issue, try retyping your code in Notepad editor and use it. This will eliminate any whitespace inconsistencies that may be present in your code and not visible to eyes (This is especially the case if you copied your code from another source)
P.S. Let the community know which one solved it for future reference.

Related

Syntax error: Expected "(" or "," or keyword SELECT but got end of script

I just followed the query from the course but I could not figure out why I get the error message.
Syntax error: Expected "(" or "," or keyword SELECT but got end of
script at [13:6]
With
longest_used_bike AS (
SELECT
Bikeid,
SUM(duration_minutes) AS trip_duration
FROM
bigquery-public-data.austin_bikeshare.bikeshare_trips
GROUP BY
Bikeid
ORDER BY
Trip_duration DESC
LIMIT 1
)
Why do I get this error?
I had the same issue. I learned that the CTE (the WITH clause) can't work as a standalone piece of code - it is a part of a larger statement. To complete your code, you must add a SELECT statement.
Here is what I think happens:
the WITH clause only creates your temporary table
you need another statement to manipulate or query the temp table, a SELECT usually works.
WITH longest_used_bike AS (
SELECT
bikeid,
SUM(duration_minutes) AS trip_duration
FROM `bigquery-public-data.austin_bikeshare.bikeshare_trips`
GROUP BY
bikeid
ORDER BY trip_duration DESC
)
/* add your SELECT statement here */
SELECT *
FROM longest_used_bike;
/* or whatever else */
You get this error because a CTE (i.e. the WITH statement) is only part of a query. It needs to be followed by another statement, usually a SELECT.
Perhaps you intend:
With longest_used_bike AS (
SELECT Bikeid, SUM(duration_minutes) AS trip_duration
FROM `bigquery-public-data.austin_bikeshare.bikeshare_trips`
GROUP BY Bikeid
ORDER BY Trip_duration DESC
LIMIT 1
)
select *
from longest_used_bike;
I also assume that you are using BigQuery. The table name needs to be inclosed in backticks.
I also ran into this issue during the course.
From the course, written under the image of code. "If you run it now, it’ll return an error because you haven’t written any queries yet. Now, it’s time to write a query that identifies the start station that this bike came out of."
To fix the issue add another SELECT statement.
I ran into the same issue during the course today. By adding a SELECT statement at the end will resolve this. In this situation, we just created a temporary table without providing any query to use it in that is why we are getting this error.
You can find more about the syntax here:https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax
The activity has a note after the creation of the temp table that says "If you run it now, it’ll return an error because you haven’t written any queries yet. Now, it’s time to write a query that identifies the start station that this bike came out of."
You just need to keep reading the activity and you will understand why errors occur.
And advice is to take a look at the activity before starting it, so you will know what you will encounter as you work through the activity.
I ran into this issue during a course.
Creating a temporary table in BigQuery without a SELECT statement at the bottom will result in this error. By adding a SELECT statement at the end will resolve the issue.
Hence, just add a statement below your created temporary table:
SELECT * FROM longest_used_bike
You Must Add your Query Since You Just created a 'Temporary Table' which will
long last for the next 60 minutes, and you didn't add your query after creating a temp table so that's why you're getting an error.
As you created a temporary table add your query just below the temp table whithout ";" for reference look at this
With
longest_used_bike AS (
SELECT
Bikeid,
SUM(duration_minutes) AS trip_duration
FROM
bigquery-public-data.austin_bikeshare.bikeshare_trips
GROUP BY
Bikeid
ORDER BY
Trip_duration DESC
LIMIT 1
)
-- Example --
SELECT *
FROM longest_used_bike;

SQL GROUP BY 1 2 3 and SQL Order of Execution

This may be a dumb question but I am really confused. So according to the SQL Query Order of Execution, the GROUP BY clause will be executed before the SELECT clause. However it allows to do something like:
SELECT field_1, SUM(field_2) FROM myTable GROUP BY 1
My confusion is that if GROUP BY clause happens before SELECT, in this scenario I provided, how does SQL know what 1 is? It works with ORDER BY clause and it makes sense to me because ORDER BY clause happens after SELECT.
Can someone help me out? Thanks in advance!
https://www.periscopedata.com/blog/sql-query-order-of-operations
My understanding is because it's ordinal notation and for the SELECT statement to pass syntax validation you have to have at least selected a column. So the 1 is stating the first column in the select statement since it knows you have a column selected.
EDIT:
I see people saying you can't use ordinal notation and they are right if you're using SQL Server. You can use it in MySQL though.
select a,b,c from emp group by 1,2,3. First it will group by column a then b and c. It works based on the column after the select statement.
Each GROUP BY expression must contain at least one column that is not an outer reference. You cannot group by 1 if it is not a column in your table.

Selecting the biggest ZIP code from a column

I want to get the biggest ZIP code in DB. Normally I do this
SELECT *
FROM (
Select * From tbuser ORDER BY zip DESC
)
WHERE rownum = 1
with this code I can get the biggest zip code value without a duplicate row (since zip code is not a primary key).
But the main company at Japan said that I cant use it since when the connection is slow or the DB have very large data, you cant get the right row of it. It will be a great help for me if someone can helps.
I want to get the biggest ZIP code in DB.
If you really only want the zip code, try that:
SELECT MAX(zip) FROM TBUSER;
This will use the index on the zip column (if it exists).
That being said, Oracle is usually smart enough to properly optimize sub-query selection using ROWNUM. Maybe your main company is more concerned about the possible "full table" ̀ORDER BY` in the subquery ? OTH, if the issue is really with "slow network", maybe worth taking some time with your DBA to look on the wire using a network analyzer or some other tool if your approach really leads to "excessive bandwidth consumption". I sincerely doubt about that...
If you want to retrieve the whole row having the maximum zip code here is a slight variation on an other answer (in my opinion, this is one of the rare case for using a NATURAL JOIN):
select * from t
natural join (select max(zip) zip from t);
Of course, in case of duplicates, this will return multiple rows. You will have to combine that with one of the several options posted in the various other answers to return only 1 row.
As an extra solution, and since you are not allowed to use ROWNUM (and assuming row_number is arbitrary forbidden too), you can achieve the desired result using something as contrived as:
select * from t
where rowid = (
select min(t.rowid) rid from t
natural join (select max(zip) zip from t)
);
See http://sqlfiddle.com/#!4/3bd63/5
But honestly, there isn't any serious reason to hope that such query will perform better than the simple ... ORDER BY something DESC) WHERE rownum <= 1 query.
This sounds to me like bad advice (masquerading as a rule) from a newbie data base administrator who doesn't understand what he's looking at. That insight isn't going to help you, though. Rarely does a conversation starting with "you're an obstructionist incompetent" achieve anything.
So, here's the thing. First of all, you need to make sure there's an index on your zip column. It doesn't have to be a primary key.
Second, you can try explaining that Oracle's table servers do, in fact, optimize the ... ORDER BY something DESC) WHERE rownum <= 1 style of query. Their servers do a good job of that. Your use case is very common.
But if that doesn't work on your DBA, try saying "I heard you" and do this.
SELECT * FROM (
SELECT a.*
FROM ( SELECT MAX(zip) zip FROM zip ) b
JOIN ZIP a ON (a.zip = b.zip)
) WHERE rownum <= 1
This will get one row with the highest numbered zip value without the ORDER BY that your DBA mistakenly believes is messing up his server's RAM pool. And, it's reasonably efficient. As long as zip has an index.
As you are looking for a way to get the desired record without rownum now, ...
... here is how to do it from Oracle 12c onward:
select *
from tbuser
order by zip desc fetch first 1 row only;
... and here is how to do it before Oracle 12c:
select *
from (select tbuser.*, row_number() over(order by zip desc) as rn from tbuser)
where rn = 1;
EDIT: As Sylvain Leroux pointed out, it is more work for the dbms to sort all records rather than just find the maximum. Here is a max query without rownum:
select *
from tbuser where rowid =
(select max(rowid) keep (dense_rank last order by zip) from tbuser);
But as Sylvain Leroux also mentioned, it makes also a difference whether there is an index on the column. Some tests I did show that with an index on the column, the analytic functions are slower than the traditional functions. Your original query would just get into the index, go to the highest value, pick the record and then stop. You won't get this any faster. My last mentioned query being quite fast on a none-indexed column is slower than yours on an indexed column.
Your requirements seem arbitrary, but this should give you the result you've requested.
SELECT *
FROM (SELECT * FROM tbuser
WHERE zip = (SELECT MAX(zip) FROM tbuser))
WHERE rownum = 1
OK - try something like this:
SELECT *
FROM TBUSER
WHERE ZIP = (SELECT MAX(ZIP) FROM TBUSER);
Fetch a single row from a cursor based on the above statement, then close the cursor. If you're using PL/SQL you could do it like this:
FOR aRow IN (SELECT *
FROM TBUSER
WHERE ZIP = (SELECT MAX(ZIP) FROM TBUSER))
LOOP
-- Do something with aRow
-- then force an exit from the loop
EXIT;
END LOOP;
Share and enjoy.
I was wondering that nobody posted this answer yet. I think that is the way, you should do something like that.
SELECT *
FROM (
Select a.*, max(zip) over () max_zip
From tbuser a
)
WHERE zip=max_zip
and rownum = 1
Your query gets exactly one random row of all records having the max zip code. So it cannot be the problem that you retrieve a record with another zip code or more than one record or zero records (as long as there is at least one record in the table).
Maybe Japan simply expects one of the other rows with that zip code? Then you may just have to add another order criteria to get that particular desired row.
Another thought: As they are talking about slow connection speed, it may also be that they enter a new max zip code on one session, query with another and get the old max zip, because the insert statement of the other session hasn't gone through yet. But well, that's just the way this works of course.
BTW: A strange thing to select a maximum zip code. I guess that's just an example to illustrate the problem?
IF you are getting multiple records using MAX function (which is not possible, but in your case you are getting, I don't know how until you post screenshot) then You can use DISTINCT in your sql query to get single record
SELECT DISTINCT MAX(zipcode) FROM TableUSER
SQL FIDDLE

Convert rownum() from db2 to Oracle

Good day,
I would like to change some program code (mostly on SQL code) because the database already change from DB2 to Oracle.
Here is 1 example that I successful changed but I am not really understand about it, and I cant find it from google.
The following is the original SQL Query code (using DB2) :
SELECT *
FROM (SELECT T0.CREATEDBY AS C1, row_number() OVER ( ORDER BY T0.GROUPNAME) AS rownum
FROM IBSADMIN.CCGROUP T0
WHERE T0.GROUPID != 0001 AND T0.GROUPID != 001 AND T0.CHANNEL = 'CC') AS tname
WHERE rownum BETWEEN 1 AND 20
Here is the SQL Query code after edit by me (successfully get data from Oracle) :
SELECT *
FROM (SELECT T0.CREATEDBY AS C1, row_number() OVER ( ORDER BY T0.GROUPNAME) AS rownum1
FROM IBSADMIN.CCGROUP T0
WHERE T0.GROUPID != 0001 AND T0.GROUPID != 001 AND T0.CHANNEL = 'CC') tname
WHERE rownum1 BETWEEN 1 AND 20
As I analyze, I get error if I didnt change the rownum to rownum1, error is ORA-00923: FROM keyword not found where expected .Thus I change it to rownum1, I think the rownum should be a keyword in DB2, is there any keyword like this for Oracle also?
In the line 4 last part, from DB2 code, it end with As tname. If I put the same things in Oracle code, I get error ORA-00933: SQL command not properly ended . Thus I erase the As . I not so understand how is the As tname means, As the SQL query in the bracket:
(SELECT T0.CREATEDBY AS C1, row_number() OVER ( ORDER BY T0.GROUPNAME) AS rownum1
FROM IBSADMIN.CCGROUP T0
WHERE T0.GROUPID != 0001 AND T0.GROUPID != 001 AND T0.CHANNEL = 'CC')
It return me 2 columns, thus I am not understand how is the As tname interate with the 2 column.
Kindly advise.
rownum is a reserved word in Oracle-- in Oracle, rownum is a pseudocolumn that you can reference to get the row number (before ordering) of a result set. That's why you need to change the alias when you convert to Oracle. I would prefer something that was more obviously different from rownum-- rn or rnk are good options.
tname is an alias for the inline view in your query. In Oracle, you cannot use the AS keyword to assign a table alias (you can optionally use it when defining a column alias which is why AS rownum1 is valid but you could also get rid of the AS entirely). In this case, the tname alias is never used so in Oracle you could omit it. I know in some databases (SQL Server) aliases for inline views are required-- I'm not sure whether DB2 requires the table alias.
It sounds like you modified the query correctly (though I quibble with the alias you chose instead of rownum).
May be nobody is still interested in this, but I found this solution here:
http://www.sqlines.com/db2-to-oracle/fetch_first_rows_only
use FETCH FIRST x ROWS ONLY, something like:
select * from a_table FETCH FIRST 1 ROWS ONLY;
will give you only the first line of the table, I've used this and it worked just as I expected.

Simple SELECT query problem

I have this MySql select query which seems to have a bug but I am quite "green" so I simply cannot see, so maybe you could help?
Here is the query:
SELECT node_id
FROM rate
WHERE node_id='".$cat_node_id_string."'
LIMIT ".$node_count_star.",".$node_count_end."
ORDER BY SUM(amount)
GROUP BY node_id
Thanks for help in advance...
UPDATE:
I will post a mysql error to make it clearer...
You have an error in your SQL syntax;
check the manual that corresponds to
your MySQL server version for the
right syntax to use near 'GROUP BY
node_id LIMIT 1,20' at line 5
try this
SELECT node_id
FROM rate
WHERE node_id='".$cat_node_id_string."'
ORDER BY SUM(amount)
GROUP BY node_id
LIMIT ".$node_count_star.",".$node_count_end."
Be aware though, that the result will be a single record containing whatever $cat_node_id_string resolves to!
With WHERE node_id='".$cat_node_id_string."' you tell MySQL to only return those records where node_id matches an exact string.
With GROUP BY node_id you tell MySQL to group all records into one
Your error:
GROUP BY node_id LIMIT ,'
That comma there suggests that your limit variables $node_count_star and $node_count_end are empty.
Cheers & good luck.