Bind Dates in SQL Tuning advisor - sql

I'm trying to bind a date to a variable using Oracle SQL Developers SQL Tuning advisor, but it recognizes it as a VARCHAR2 and not a DATE. Is there a way to specify the data type of the parameters you bind?
SQL:
SELECT * FROM Actv
WHERE ActvId = :in_UserGrpCds AND ActvTime >= :in_FromDate AND ActvTime < :in_ThruDate
OFFSET :in_CurrRecordOffset FETCH NEXT :in_NextRecordOffset ROWS ONLY;
The in_ThruDate get's bound as a VARCHAR2 and it can't run the tune.
Bind Variables :
1 - (NUMBER):1091
2 - (NUMBER):0
3 - (VARCHAR2):07-21-2018
4 - (NUMBER):50000
5 - (VARCHAR2):08-21-2018
-------------------------------------------------------------------------------
ERRORS SECTION
-------------------------------------------------------------------------------
- ORA-00932: inconsistent datatypes: expected DATE got NUMBER
-------------------------------------------------------------------------------

We only bind strings/numbers/nulls so adjust your SQL to include the to_date:
SELECT * FROM Actv
WHERE ActvId = :in_UserGrpCds
AND ActvTime >= to_date(:in_FromDate ,'MM-DD-YYYY')
AND ActvTime < to_date(:in_ThruDate ,'MM-DD-YYYY')
OFFSET :in_CurrRecordOffset FETCH NEXT :in_NextRecordOffset ROWS ONLY;

Related

sql datetime in sas date format

proc sql noprint;
%let today=%sysfunc(today(),yymmdd10.);
%put &today.;
select
COALESCE(sum(abc.step_sum),0)
into :SumLoans_12m
from
RTDM_ABT.ABT_CONTRACT abc
where abc.CLIENT_ID = "&T_CLIENT_ID"
and abc.CONTRACT_BEGINDATE - &today. <= 360
and abc.DML_FLAG NE 1;
quit;
I understand it is necessary to convert CONTRACT_BEGINDATE (2021-01-14 00:00: 00.000) to format SAS, I think it would help , how do you do that? Thanks for your help!
ERROR:
SYMBOLGEN: Macro variable TODAY resolves to 2021-05-18
2021-05-18
SYMBOLGEN: Macro variable T_CLIENT_ID resolves to 00000031-B081-4E97-9437-F20CF874F857
MPRINT(MEQUIBEHSCOREUPRE): select COALESCE(sum(abc.step_sum),0) into :SumLoans_12m from RTDM_ABT.ABT_CONTRACT abc where abc.CLIENT_ID = "00000031-B081-4E97-9437-F20CF874F857" and
abc.CONTRACT_BEGINDATE - today() <= 360 and abc.DML_FLAG NE 1;
175369 1621341661 no_name 0 SQL (503
SQLSRV_39799: Prepared: on connection 0 175370 1621341661 no_name 0 SQL (503
SELECT * FROM rtdm_abt . ABT_CONTRACT 175371 1621341661 no_name 0 SQL (503
175372 1621341661 no_name 0 SQL (503
SAS_SQL: Unable to convert the query to a DBMS specific SQL statement due to an error. 175373 1621341661 no_name 0 SQL (503
ACCESS ENGINE: SQL statement was not passed to the DBMS, SAS will do the processing. 175374 1621341661 no_name 0 SQL (503
Try comparing the datetime variable to a datetime value. First let's rewrite your expression to make it easier to code. The comparison abc.CONTRACT_BEGINDATE - <TODAY> <= 360 is the same as abc.CONTRACT_BEGINDATE <= 360 + <TODAY>. So let's make a macro variable that contains that datetime value.
%let now_plus_360_days = %sysfunc(intnx(dtday,%sysfunc(datetime()),360)) ;
And then use that macro variable in the expression
and abc.CONTRACT_BEGINDATE <= &now_plus_360_days
proc sql noprint;
select sum(step_sum)
into :SumLoans_12m
from
RTDM_ABT.ABT_CONTRACT abc
where abc.client_id = "&T_CLIENT_ID"
and abc.DML_FLAG <> 1
and datepart(abc.CONTRACT_BEGINDATE) between today() - 365 and today()
;
quit;
It worked for me, in double it's nice that I came up with it myself))
SAS date values are integers and are the number of days from epoch 01-JAN-1960.
TODAY() returns a SAS data value, an integer nnnnn.
You are formatting that value as yymdd10. which produces a string with construct yyyy-mm-dd. (The string is more understandable to humans than the data value nnnnn.) and assigning that string to macro symbol today. When the symbol is resolved the string is inserted into your step as source code.
So,
abc.CONTRACT_BEGINDATE - &today. <= 360
becomes
abc.CONTRACT_BEGINDATE - 2021-05-18 <= 360
You want to resolve the macro symbol in the context of a SAS date literal which is construct "dd-mon-yyyy"D
Try
%let today_literal = "%sysfunc(today(),date11.)"D;
%put &=today_literal;
and
abc.CONTRACT_BEGINDATE - &today_literal <= 360
However, a lot depends on the options of the libname statement for RDTM_ABT that you do not show. You might be required to use pass-through SQL statement in order to get the result you want
connect using RDTM_ABT;
select * from connection to RDTM_ABT
(
... my query in remote database syntax ...
)
You could use the remote system functions for today, or construct the query using the appropriate source code for the remote system date literal or string to date conversion functions.

SAS YYMMDD10. works but YYMMDDn10 doesn't

This is my data (sorry for no script, it's just proc create table from mssql):
testdb.testtable
id - numeric
date_from - numeric (datetime from mssql)
date_to - numeric (datetime from mssql)
base_id - numeric
base_id2 - string (length 64)
What I tried to do was:
proc sql;
update testdb.testtable tt
set base_id2 = CATX('_',
('data from other table'),
put(datepart(date_from),yymmddn10.),
put(datepart(date_to),yymmddn10.),
put(base_id,z4.)
)
where (....)
;
quit;
And I get this error:
The width value for YYMMDDN is out of bounds. It should be between 2 and 8.
The width value for YYMMDDN is out of bounds. It should be between 2 and 8.
What I really don't understand is that when I use format with separators, YYMMDD10., it works.
When i run:
proc sql;
select datepart(date_from) format=yymmddn10. from testdb.testtable;
quit;
It returns 20191227 - It's great. When I run
proc sql;
select put(datepart(date_from),yymmddn10.) from testdb.testtable;
quit;
It fails with the same error.
What do I miss?
There seems to be a bug in PROC SQL that allows you to attach a format that cannot work (the maximum width needed for a date without separators is 8 bytes).
It is also interesting that PROC PRINT (and the simple SELECT query in PROC SQL, like in your example) do not mind that the format width is invalid.
542 data test1;
543 now=date();
544 run;
NOTE: The data set WORK.TEST1 has 1 observations and 1 variables.
545
546 data test2 ;
547 set test1;
548 format now yymmddn10.;
----------
29
ERROR 29-185: Width specified for format YYMMDDN is invalid.
549 run;
NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.TEST2 may be incomplete. When this step was stopped there were 0 observations
and 1 variables.
WARNING: Data set WORK.TEST2 was not replaced because this step was stopped.
550
551 proc sql;
552 create table test2 as select now format=yymmddn10. from test1;
NOTE: Table WORK.TEST2 created, with 1 rows and 1 columns.
553 select * from test2;
554 quit;
555
556 proc print data=test2;
557 run;
NOTE: There were 1 observations read from the data set WORK.TEST2.
558
559 data test3;
560 set test2;
561 run;
ERROR: Width specified for format YYMMDDN is invalid.
NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.TEST3 may be incomplete. When this step was stopped there were 0 observations
and 1 variables.
WARNING: Data set WORK.TEST3 was not replaced because this step was stopped.
Also interesting is that if you use that format specification in PROC FREQ
proc freq data=test2; tables now; run;
it adds a space and a 'F7'x character in front of the data string.
The FREQ Procedure
Cumulative Cumulative
now Frequency Percent Frequency Percent
---------------------------------------------------------------
รท20200218 1 100.00 1 100.00
The number in format is the given width. Format YYMMDDn has 8 chars, so I should have used YYMMDDn8. And it worked.
I was having a long struggle with it and I still don't understand why did it work in format= and not in put().

Why does "WHERE (Time_Stamp >= TDateTime-variable)" ignore fractional seconds?

Using Delphi 6 and Microsoft SQL Server 2000.
I need to extract records where a TDateTime Field is > a passed TDateTime, "FromDate".
It fails as if the fractional part of the seconds of the passed TDateTime are always zero.
Debug printouts confirm that the fractions are there.
The WHERE part ignores the fraction part of :Fdate.
Assume the following 3 records:
Record 1: Time_Stamp is 1.2
Record 2: Time_Stamp is 1.4
Record 3: Time_Stamp is 1.6
The value 1.3 is then sent to the Query in :Fdate.
The resulting dataset returns ALL 3 records.
I expected only records 2 and 3 since 1.3 > 1.2
The 'Time_Stamp' field in database is a SQL 'datetime' field.
Everything works perfectly for integer seconds,
i.e. one record per second, or less often, when the decimal fraction is unimportant.
Can anyone point out where my error is?
The SQL statement is generated by code (shown below) as follows:
SELECT TOP 6 * FROM T_TransactionLog
INNER JOIN T_LookUp_TransTypes
ON T_TransactionLog.TransType = T_LookUp_TransTypes.TransType
WHERE (Time_Stamp >= :Fdate)
AND T_TransactionLog.TransType IN (
3,
4,
5
)
AND LockerNo < 60001
ORDER BY Time_Stamp ASC
The code is as follows:
Query.Connection := Sys_DB_Form.ADOConnection;
DataSource.DataSet := Query;
Query.SQL.Add('SELECT TOP ' + IntToStr(cNoTransactions) + ' * FROM
T_TransactionLog');
Query.SQL.Add('INNER JOIN T_LookUp_TransTypes');
Query.SQL.Add('ON T_TransactionLog.TransType =
T_LookUp_TransTypes.TransType');
Query.SQL.Add('WHERE (Time_Stamp ' + S_Condition + ' :Fdate)');
Query.SQL.Add('AND T_TransactionLog.TransType IN (');
Query.SQL.Add(IntToStr(ord(Apl_TrLog.ttEA)) + ',');
Query.SQL.Add(IntToStr(ord(Apl_TrLog.ttMO)) + ',');
Query.SQL.Add(IntToStr(ord(Apl_TrLog.ttMC)));
Query.SQL.Add(')');
Query.SQL.Add('AND LockerNo < ' +
IntToStr(Apl_Config.cLNoOfFirstgate));
if Locker <> 0 then
begin
Query.SQL.Add('AND LockerNo = ' + IntToStr(Locker));
end;
Query.SQL.Add(S_OrderBy);
Query.Parameters.FindParam('Fdate').Value := FromDate; // <<< Fail????
Query.SQL.SaveToFile(GetApplicationDataPath + 'Sql.txt');
try
Query.Open;
except
ShowMessage('Query open fail on ME Show Transaction log');
end;
Please chech the accuracy note for SQL Server datetime and time data types on MSDN
It is written that:
Accuracy Rounded to increments of .000, .003, or .007 seconds
This means
23:59:59.997
is OK
But
23:59:59.998
will be rounded to 23:59:59.997
And
23:59:59.999
will be rounded to 00:00:00 for the next day

Script to generate data, SQL oracle 10g

I'm trying to build a script that insert random datas into my table.
My actual script looks like that :
INSERT INTO Utilisateurs (id_utilisateur, Uti_nom, Uti_prenom, Uti_role, Uti_mdp, Uti_Statut)
SELECT
-- here to input the id (number that increment each time)
dbms_random.string('A', trunc(dbms_random.value(5, 50))), -- data for uti_nom
dbms_random.string('A', trunc(dbms_random.value(5, 100))), -- data for uti_prenom
-- randomly get 'Administrateur' or 'Utilisateur'
dbms_random.string('X', 10), -- data for uti_mdp
trunc(dbms_random.value(0, 1)) -- data for uti_status
FROM dual
CONNECT BY LEVEL < 100;
So if someone can help me to get the both comment line...
There's a sample, but what i really need it's the ID that increments and Uti_role (Administrateur/Utilisateur) the others fields can be generated and looks like "dsjhadakj"
id_utilisateur Uti_nom Uti_prenom Uti_role Uti_mdp Uti_Statut
d--------+---------+---------+---------+---------+---------+---------+---------+
1 Elche Marco Administrateur Haj432Hgn 1
2 Babo Jules Utilisateur Haj432Hgn 0
3 Ghale Alex Administrateur Haj432Hgn 1
For self-incremental ID you can use LEVEL
For uti_role something like this:
CASE WHEN dbms_random.value(0, 1) > 0.5 THEN 'Administrateur' ELSE 'Utilisateur' END
Here's SQL Fiddle for just the SELECT part.

Oracle - Add rows together in one field

Using the following code. Keep getting the following error
Select distinct
ship_L.ship_ID,
ship_L.Item_Num,
C.sku,
C.ob_oid,
c.Container
From (
Select distinct
ob_oid,
sku,
substr((ltrim(sys_Connect_By_Path(trim(to_Cont),' / '))),2,(length(ltrim(sys_Connect_By_Path(trim(to_Cont),' / '))))) as Container
From (
Select distinct
Ob_oid,
sku,
To_Cont,
row_number() Over (Partition by sku order by to_Cont) -1 as seq
From (
Select distinct
ob_oid,
sku,
To_Cont
from elite_76_w1.ITH_f
--Where ob_oid = '237472'
-- and sku = '64154'
)
)
Where connect_By_Isleaf = 1
Connect by seq = Prior seq +1 and sku = Prior sku
Start with seq = 1
) C
Left Join elite_76_D.ship_L
on ship_L.ship_id = C.ob_oid
and ship_L.item_num = C.sku
WHere C.ob_oid = '237472'
and C.sku = '64154'
Getting this error:
ORA-01489: result of string concatenation is too long 01489. 00000 - " result of string concatenation is too long" *Cause: String concatenatin result is more than the maximun size. * Action: Make sure that the result is lees than the maximum size. Vendor Code 1489Error at line 3.
Start with:
SKU Location
64154 A153945
64154 A153943
64154 A153947
64154 A153946
64154 A153944
Need:
64154 A153944 / A153945 / A153946 / A153947
Thank you for all the help,
David
ORA-01489: result of string concatenation is too long means that part of your SQL is generating a string longer than 4000 characters, which is the limit of a VARCHAR2 in SQL.
You can't truncate the string in SQL (e.g. with SUBSTR), because SQL needs to construct the string before it sends it to the SUBSTR function; and it bails because it exceeds the limit.
To solve this you'll probably need to create your own PL/SQL function, in which you have a greater length limit (32k) for VARCHAR2s.