Using Dynamic Variables in Oracle SQL Developer - sql

Trying to setup a WHILE LOOP in Oracle SQL Developer but I'm having a lot of trouble trying to set/define a variable. I'm used to working in PHP where I would declare this on my PHP scripts.
Here is what I have below. The script is unfinished I am basically going to have it loop through weeks when it is done.
VARIABLE MYDateVar2 varchar2(40);
EXEC :MYDateVar2 := '01-JAN-14';
select customer_name,
sum(CASE when to_char(to_date(PLANNED_SHIP_DATE), 'WW') = 40 then (REVISED_QTY_DUE - QTY_SHIPPED) * SALE_UNIT_PRICE end) as Wk40
from customer_order_join
where planned_ship_date >= :MYDateVar2
group by customer_name;
So I am having trouble basically placing the variable 'MYDateVar2' back into the script. I've tried using ## and : before but Oralce SQL Developer keeps prompting me for values. I also know I should probably set the varchar to be DATE but that should be fine for now.
Can someone please let me know how I properly insert a variable into the script? Thanks!

What you're doing is fine, as long as you tell SQL Developer to run the whole script, not just the select statement; you need to Run Script (F5), rather than Run Statement (Ctrl+Enter). If it runs the statement stand-alone then it will always prompt for the bind variable value.
Not directly relevant, but... presumably you've used a date format that is valid for your client's NLS settings, but you shouldn't rely on that; it's safer to always explicitly set the format:
where planned_ship_date >= to_date(:MYDateVar2, 'DD-MON-RR')
If you're going to loop, though, then you need to be writing PL/SQL, so you might as well declare the variable inside the block rather than at client level, unless you want to pass the same value into multiple blocks or stored procedure calls.

Related

Pulling a SQL Server date to be used in Oracle query within SSIS environment is ignored in the Oracle query

I am having trouble in my Oracle query that uses a variable stored in SSIS which has a date that is pulled from sql server.
I am using an execute sql task that simply gets a max date from a sql server table and stores it in a variable. E.g.
SELECT MAX(t.Date) FROM table t;
I then want to use that variable in my Oracle query which is an ADO.NET source connection. I noticed you can't parameterize in those connections and found the work around where you use the sql expression with your user variable in it. So now my Oracle source query looks something like this:
"SELECT DISTINCT t.* FROM table t WHERE TO_CHAR(t.LastUpdateDate, 'YYYY-MM-DD') > " + "'#[User::LastUpdateDate]'"
The query syntax itself is fine, but when I run it, it is pulling all rows and seems to be completely ignoring the where clause of the date.
I've tried removing the TO_CHAR from LastUpdateDate.
I've tried adding a TO_CHAR to my user variable #[User::LastUpdateDate].
I've tried using the CONVERSION() function from sql server on #[User::LastUpdateDate].
Nothing seems to work and the query just runs and pulls in all data as if I don't have the WHERE clause on the query.
Does anyone know how to rectify this issue or point out what I might be doing wrong?
Thank you for any and all help!
**EDIT:
My date being pulled from SQL Server is in this format: 2022-09-01 20:17:58.0000000
This is not an answer, just troubleshooting advice
You do not say what data type #[User::LastUpdateDate] is, I'll assume it's a datetime
Ideally all datetime data should be kept in datetime data types, then format becomes completely irrelevant. However since it's difficult to parameterise Oracle queries in SSIS, you have to concoct a string to be submitted. Now date format does become important.
On to something a little different, it is a very good habit performancewise, to not put functions around columns that you are searching on. This is called sargability - look it up.
Given these things, I suggest that you concoct your required SQL query bit by bit and troubleshoot.
First, format your date parameter as an Oracle date literal. Remember this is normally a bad and unecessary thing. We are only doing it because we have to concoct a SQL string.
So create another SSIS variable called strLastUpdateDate and put this hideous expression in it:
RIGHT("0" + (DT_STR,2,1252)DATEPART( "dd" , #[User::LastUpdateDate] ), 2) + '-' +
(DT_STR,3,1252)DATEPART( "mmm" , #[User::LastUpdateDate] ) + '-' +
(DT_STR,4,1252)DATEPART("yyyy" , #[User::LastUpdateDate] )
Yes this is ludicrously long code but it will turn your date variable into a Oracle string literal. You could simplify this by putting it into your original max query but lets not go there. Use whatever debugging technique you have to confirm that it works as expected.
Now you should be able to use this:
"SELECT t.*, '"+#[User::LastUpdateDate]+"' As MyStrDate FROM table t WHERE
t.LastUpdateDate > '" #[User::strLastUpdateDate] + "'"
You can try running that and see if it makes any difference. Make sure you use this https://dba.stackexchange.com/questions/8828/how-do-you-show-sql-executing-on-an-oracle-database to monitor what is actually being submitted to Oracle.
This is all from memory and googling - I haven't done SSIS for many years now
I suspect after all this you may still have the same problem because I recall from many years having the same mysterious issue.

Is it possible to tell which Oracle cluster node was called?

I'm getting different sysdate results depending on the node. But how to figure out which are the problematic nodes?
Assuming you are able to connect via sqlplus or another tool and assuming you are using TNS names.....
If the assumptions above are correct your TNS names will look somthing like the below
(DESCRIPTION=
(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=tcp)(HOST=sales1-server)(PORT=1521))
(ADDRESS=(PROTOCOL=tcp)(HOST=sales2-server)(PORT=1521)))
(CONNECT_DATA=(SERVICE_NAME=sales.us.example.com)))
You can then simply remove all nodes except 1 (backing up file first of course) then connect to via SQLPULS or your tool of choice and do..
select sysdate from dual;
Rinse and repeat for each of the nodes in the TNSNames original file, until you find which are the problematic nodes, although I am unsure of any reason that different nodes would give a different sysdate.
This query tells you which node your session is using:
select * from v$instance;
You can use the undocumented GV$ table function to run a query against all RAC instances to find out which ones have a bad clock. The function is a bit tricky because the cursor gets parsed on your instance but executed on all the instances. It's not always clear exactly where the code is running, and you may have to create a PL/SQL function to ensure that the code is truly executing on the remote instance.
create or replace function get_sysdate return date is
begin
return sysdate;
end;
/
select * from
table(gv$(cursor(
select instance_name, get_sysdate from v$instance
)));
Unfortunately I am not able to fully test the above code since I don't have access to change the time on any RAC clusters. But I've used similar code in the past.

Datetime type conversion in SQL

I am getting data from some external datasource and need to store in SQL server table. But one filed in it is Datetime. But I am getting that datetime field as Varchar format, and now in my SQL table I need to save it as DateTime datatype.
CONVERT(DATETIME,[Date_time],03)
-- This code work in my Development Environment but not in Production.
CONVERT(DATETIME,[Date_time],120)
-- This code work in my Production but not in development.
This make my life difficult to transfer code from development to Production since I have to make changes in tested code.
Please note that I am using SQL server 2008 R2.
Is there anyway that I can make code similar? I cannot change the culture and language on both server since many other applications are deployed there and it might break existing application in both server.
You can try to use a SET statement to override the date format, something like this:
SET DATEFORMAT mdy;
SELECT CONVERT(DATETIME, [Date_Time], 120);
As long as you include this code in your stored procedure/query on both environments, this should be fine. You may want to read up about this on MSDN.
A workaround for your problem would be to provide a feature that calculates (or defines) the correct style for each environment. This simplest option would be a user-defined function.
CREATE FUNCTION [dbo].[fnCustomDateStyle]()
RETURN int AS
BEGIN
RETURN 3 # Or 120, in the other environment
END
Which can be used in every environment thus:
CONVERT(DATETIME, [Date_Time], fnCustomDateStyle())

How do I declare a variable for a hard coded database?

I have some hard coded database values in my SQL and I need to convert to variables , I have declared them in places but I need Production2 to be changed to #Source_Database_Name variable below but I dont know how to place it in with the Information Schema just after it without getting a syntax error
IF EXISTS(SELECT * FROM Production2.INFORMATION_SCHEMA.COLUMNS
I guess that the only way you can do this is dynamic sql generation (unfortunately). And there's actually quite a few reasons (from database engine's perspective) for not allowing a user to parametrise queries in a way you want. The one that sits on top of my head is that it will make impossible to validate syntax of your query (no way to know that you're referring to what actually exists).
In case you're talking about "being able to execute the same set of SQL against different database(s)" and you're actually executing this sql from code (.NET / anything), you can achieve the same result by specifying target database in connection string (i.e. by changing the level where you set database -- not in the [sql] script, but rather at some external point).

Store Procedures in SQuirrel 3.2.1 when using it with a JDBC driver for a DB2 database

I expend a lot of time trying to retrieve data from a Stored Procedure, here is the code
CREATE PROCEDURE aprocedure(
IN idin CHAR,
OUT returnvalue CHAR)
AS:
SET returnvalue=
(SELECT something
FROM sometable
WHERE id=idin)
I could create it, with no problems, but when I tried to call it like this:
call someprocedure('theid', ?)
Error -313 kept poping out, I did my homework and check the web, IBM forums were no help at all, I couldnt find any documentation, specifications, or anything that make this more clear, also SQL error code -313 means that the number of parameters in the procedure does not match the number of parameters you're using when you call it. So, after too much research, I started thinking that DB2 with JDBC driver and or SQuirreL have trouble when returning OUT values, (I also installed a DB2 CTL client, created a local database, created a table, created the procedure, I called, and everything worked nicely) so I change my code to this (to use a Result Set instead of an OUT):
CREATE PROCEDURE someprocedure(IN idin CHAR (22))
DYNAMIC RESULT SETS 1
P1: BEGIN
DECLARE cursor1 CURSOR WITH RETURN FOR
SELECT something FROM sometable WHERE id=idin;
OPEN cursor1;
END P1
aaaaaaaaaaaand NOTHING, SQuirreL gave me some error codes, when trying to create it, so... I enter that same code in Aqua Data Studio 4.7, and worked like a charm, I call the procedure from Aqua Data like this:
call someprocedure('theid');
and it returned what was supposed to return, I tried that same sentence with SQuirreL...
and it WORKED too !!
Im sure that my sintaxys was correct all along, even with the OUT type of return, so, my question, finally is this.
Does SQuirreL check the input you enter before passing it to the JDBC?
Also
Where do I can find how exactly DB2 is altering SQL code?? because we all know that all DBM change the SQL a bit, but MySQL have great documentation... and i honestly couldnt find any good one on DB2, also im talking about "pure" SQL since in DB2 you can enter stored procedures in C , Java etc...