I am trying to pass PL/SQL query from file via VBA to the Oracle DB.
Simple test query like SELECT * FROM DUAL
works flawlessly.
However just a bit more complicated (even not yet PL/SQL) like
SELECT x, y, z FROM table WHERE DATE = '5may2017'
already fails (actually no explicit error, just empty result).
I'm connecting to Conn.Provider = "OraOLEDB.Oracle.1", apply user schema by ALTER SESSION SET CURRENT_SCHEMA=MyUserSchema. Finally my last code-snippet is:
With Cmd
.Properties("PLSQLRSet") = True '(actually this line doesnt affect)'
.ActiveConnection = Conn
.CommandType = adCmdText
.CommandText = SqlStatement
Set rs = .Execute
End With
Sheets(1).Range("A1").CopyFromRecordset rs
So, excel sheet is populated with the 1st test simpliest query, however remains empty for the more complex part (I have no semicolon in the end :) )
However final sql-script will be 400+ lines long...
What am I missing at this step?
You might try instead ANSI Date 'YYYY-MM-DD' or ANSI Time 'HH:MM:SS' SQL formatting below for an implicit conversion with SQL ANSI DATE or SQL ANSI TIME operator.
SELECT x, y, z FROM table WHERE COLUMN_DATE = DATE '2017-05-05'
SELECT x, y, z FROM table WHERE COLUMN_TIME = TIME '23:59:59'
- according such "COL_" exists
A must-keep cheatsheet for quick reference PSOUG Datatypes
NB: For Toad users, check your NLS SELECT * FROM NLS_SESSION_PARAMETERS;
; your NLS_DATE_FORMAT is not default one DD-MON-RR.
Related
SELECT b.*
FROM buses b,
bus_stations bs,
starts st,
stops_at sa
WHERE st.station_no = ( SELECT station_id
FROM bus_stations
WHERE station_name = "golden mile_Regina"
)
AND sa.station_no = ( SELECT station_id
FROM bus_stations
WHERE station_name = 'westmount_edmonton'
)
ORDER BY DATE;
You can't use double quotes with strings - use single ones, i.e.
WHERE station_name = 'golden mile_Regina'
By the way, are you sure of spelling & letter size? Is it really mixed case, with underscores? Just asking.
Furthermore, you're ordering by DATE - that won't work either, you can't use DATE as a column name (unless you enclose it into double quotes, but I certainly wouldn't recommend that). Have a look at the following example (stupid, yes - setting date to be a number, but I used it just to emphasize that DATE can't be used as a column name):
SQL> create table test (date number);
create table test (date number)
*
ERROR at line 1:
ORA-00904: : invalid identifier
Once you fix that, you'll get unexpected result as there are 4 tables in the FROM clause, but they aren't joined with one another, so that will be a nice Cartesian product.
wondering if there is way to validate a query before executing
Is there way to check/validate Query without executing it?
One way that we validate SQL is to add a condition to the SQL that could never be true.
Example:
long ll_rc
long ll_result
string ls_sql, ls_test
string ls_message
//Arbitrary SQL
ls_sql = "SELECT * FROM DUAL"
//This SQL when executed will always return 0 if successful.
ls_test = "select count(*) from ( " + ls_sql + " WHERE 1 = 2 )"
DECLARE l_cursor DYNAMIC CURSOR FOR SQLSA ;
PREPARE SQLSA FROM :ls_test;
OPEN DYNAMIC l_cursor;
ll_rc = SQLCA.SQLCODE
choose case ll_rc
case 0
//Success
ls_message = "SQL is properly formed"
case 100
//Fetched row not found. This should not be the case since we only opened the cursor
ls_message = SQLCA.SQLERRTEXT
case -1
//Error; the statement failed. Use SQLErrText or SQLDBCode to obtain the detail.
ls_message = SQLCA.SQLERRTEXT
end choose
CLOSE l_cursor ; //This will fail if open cursor failed.
messagebox( "Result", ls_message )
Note: If your SQL is VERY complicated, which I suspect it isn't, the database optimizer may take several seconds to prepare your SQL. It will be significantly less time than if you run the entire query.
Since the database is the final arbitrator for what is "valid" (table and column names and such) the general answer is no. Now you could come up with a class in PB which checks statement syntax, object names, etc. so you wouldn't have to touch the db but it would be obsolete as soon as any changes were made to the db.
Put the select statement in any script and compile it. Part of the work will be to check the SQL syntax against the database you are connected to.
Watch out: you need at least one bound variable in the column list of your SQL statement. This is not the case for other DML statements.
Example:
in my case:
select noms into :ls_ttt from contacts;
results in a message Unknown columns 'noms' in 'field list'.
However,
select nom into :ls_ttt from contacts;
does not show any error.
Hope this helps.
I'm using Eclipse with Spring, Oracle SQL and JdbcTemplate. I'm trying to delete certain data based on how old the data are, the SQL command works in Oracle Sql Developer and does what I want.
DELETE from TABLE where DATE_COLUMN < SYSDATE - INTERVAL '30' DAY;
However, in my DAOImpl.java,
int thirty = 30;
String sql = "DELETE from TABLE where DATE_COLUMN < SYSDATE - INTERVAL ? DAY";
jdbcTemplate.update(sql, thirty);
I'm getting ORA-00933: SQL command not properly ended whenever I do ? and
Caused by: java.sql.SQLException: Invalid column index when I do '?' '.
I'm not sure it's ? or "?"
How do I use jdbcTemplate.update() correctly? I've tried adding the Integer.class argument and params objects but the sql command still doesn't work.
Originally I'm just trying to pass in as an int then I tried passing in a String number 30 but it still doesn't work.
I'm really not sure what I'm doing wrong.
I'm connecting to the db and everything works fine, I've tried some easier sql command like
String sql = "select count(*) from TABLE";
return jdbcTemplate.queryForObject(sql, Integer.class);
and it works and returns.
EDIT:
I can do '30' in place of my ? in my String sql = "DELETE from TABLE where DATE_COLUMN < SYSDATE - INTERVAL ? DAY"; and it runs correctly, however I do not want to hard code it.
I'm new at Oracle 11g and this forum. I just need to run a simple update statement using Oracle Merge statement because my SQL developer won't take it any other way.
The strange thing is, no matter how I try correcting the statement, even after reading many entries in this forum I still got the exact same error messages.
There are 2 different error messages, depend on how I run my statements in SQL Developer. If I run my statement as a store procedure (the update statement is a small part within a store procedure. I commented out other SQL statements and just left this update statement within the stored procedure) I got this error:
I ran this:
create or replace
PROCEDURE ADDR_UPDATE_2
AS
/* other sql statements are commented out */
MERGE INTO (SELECT id,xseq,line_1,line_2,zip,tax FROM ADDR ) b
USING (SELECT id,xseq,line_1, line_2,NVL(zip, '') AS pos_10 , NVL(tax, '') AS pos_11
FROM TEMP_ADDR ) v
ON(b.id = v.id
AND b.xseq = v.xseq)
WHEN MATCHED THEN UPDATE SET b.line_1 = v.line_1,
b.line_2 = v.line_2,
b.zip = v.pos_10,
b.tax = v.pos_11
WHERE b.line_1 <> v.line_1
OR b.line_2 <> v.line_2
OR b.zip <> v.pos_10;
/* other sql statements are commented out */
END;
and I got this error:
Error(23,9): PLS-00103: Encountered the symbol "INTO" when expecting one of the following: constant exception table long double ref char time timestamp interval date binary national character nchar
(I goggled everywhere and did not find any answer)
line 23 refers to the word "INTO"
But if I ran the above Merge statement by itself, NOT as part of a str. proc.,
I don't get any error. I got a result: 0 rows merged.
Now I modified the Merge statement into:
create or replace
PROCEDURE ADDR_UPDATE_2
AS
/* other sql statements are commented out */
MERGE INTO ADDR b
USING (SELECT id,xseq, line_1, line_2, NVL(zip, '') AS pos_10,
NVL(tax, '') AS pos_11
FROM TEMP_ADDR) v
ON(b.id = v.id
AND b.xseq = v.xseq
AND b.line_1 <> v.line_1
OR b.line_2 <> v.line_2
OR b.zip <> v.pos_10)
WHEN MATCHED THEN UPDATE SET b.line_1 = v.line_1,
b.line_2 = v.line_2,
b.zip = v.pos_10,
b.tax = v.pos_11;
/*
other sql statements are commented out
*/
END;
I got the same error:
Error(23,9): PLS-00103: Encountered the symbol "INTO" when expecting one of the following: constant exception table long double ref char time timestamp interval date binary national character nchar
line 23 refers to the word "INTO"
When I ran the statement not as part of str. proc:
I got a different error:
Error at Command Line:9 Column:8
Error report:
SQL Error: ORA-38104: Columns referenced in the ON Clause cannot be updated: "B"."LINE_2"
38104. 00000 - "Columns referenced in the ON Clause cannot be updated: %s"
*Cause: LHS of UPDATE SET contains the columns referenced in the ON Clause
*Action:
I have tried looking for answer since 2 days ago with no result, is there anyone can help how to solve this problem?
As I explained in the question referenced above, 'Columns referenced in the ON Clause cannot be updated' means that we cannot update columns in the MATCHED clause if they are included in the ON criteria.
You are in this position because you are trying to use MERGE to do something which it is not intended to do. Now you say
"I just need to run a simple update statement using Oracle Merge
statement because my SQL developer won't take it any other way."
Fnord. There is absolutely no way SQL Developer will prevent you running an update statement provided you get the syntax right. Unfortunately Oracle doesn't support the ANSI join syntax in DML statements (unlike other flovours of RDBMS), and the Oracle syntax is not intuitive:
update
(
select v.id
, v.xseq
, v.line_1
, v.line_2
, nvl(v.zip, '') AS pos_10
, nvl(v.tax, '') AS pos_11
from addr b
,temp_addr v
where ( b.id = v.id
and b.xseq = v.xseq )
and ( b.line_1 <> v.line_1
or b.line_2 <> v.line_2
or b.zip <> v.pos_10)
)
set b.line_1 = v.line_1,
b.line_2 = v.line_2,
b.zip = v.pos_10,
b.tax = v.pos_11
;
The following MERGE statement should at least compile and execute properly, although I'll agree with #APC that the right thing to do here is to use an UPDATE (because that's what you're really trying to do):
MERGE INTO ADDR b
USING TEMP_ADDR v
ON (b.id = v.id AND
b.xseq = v.xseq)
WHEN MATCHED THEN
UPDATE
SET b.line_1 = v.line_1,
b.line_2 = v.line_2,
b.zip = v.zip,
b.tax = v.tax;
I elminated the NVL manipulations you were doing because in Oracle a zero-length string (e.g. '') is the same as NULL, so the NVL calls were equivalent to saying "If this field is not NULL, return it - otherwise return NULL" which is sort of pointless.
Best of luck.
My Oracle query produces the correct result set, but data is being presented with odd characters as you can see by the blocks in the picture below.
alt text http://lh3.ggpht.com/_VSEi5_hEznA/TDtsnM9HDnI/AAAAAAAAAD8/zoEzbEaKB9s/blocks.jpg
Any reason that you can think of as to why it would do this and what these characters actually are? Below is the query I'm using. Thanks in advance.
SELECT wmsys.wm_concat(userFirstName) AS firstNames
FROM COURSESECTION
JOIN CLASSCOORDINATOR on classcoord_sectionId = coursesect_sectionId
JOIN usr_USER on classcoord_coordinatorId = userId
GROUP BY classcoord_sectionId;
If I use the same query but use a dump(wmsys.wm_concat(columnName)) then I get the data presented in the picture below.
alt text http://lh3.ggpht.com/_VSEi5_hEznA/TDx2dle4BmI/AAAAAAAAAEM/cP6opWer-Go/concat.jpg
DUMP is my starting point when investigating character set issues.
select wmsys.wm_concat('êõôó'), dump(wmsys.wm_concat('êõôó'))
from dual connect by level < 3;
In my database (AL32UTF8 as shown by querying the NLS_CHARACTERSET parameter from v$nls_parameters), this returns as expected.
How does selecting a simple userFirstName show up ?
I'd suspect that the values have come from a multi-character set environment but have somehow been treated as single character set data.
Edited to add:
I'm able to reproduce this using the following:
select * from v$nls_parameters
where parameter = 'NLS_NCHAR_CHARACTERSET';
AL16UTF16
create table t (v nvarchar2(3));
insert into t values ('a');
select dump(v) from t;
select wmsys.wm_concat(v), v, dump(v), dump(wmsys.wm_concat(v)) from t
group by v;
To remedy, you could try casting the string to a standard VARCHAR2
select wmsys.wm_concat(cast(v as varchar2(3)))
from t
group by v;