Você está na página 1de 9

'Meta-SQL' Use (with reference to PeopleSoft) Meta-SQL expands to platform-specific SQL substrings, causes another function to be called, or substitutes

a value. Meta-SQL constructs are used in functions that pass SQL strings, such as the following:

SQLExec. Scroll buffer functions (ScrollSelect and its relatives). PeopleSoft Application Designer dynamic and SQL views. Some Rowset class methods (Select, SelectNew, Fill, and so on.). The SQL class. PeopleSoft Application Engine programs. Some Record class methods (Insert, Update, and so on.). COBOL functions.

Meta-SQL Element
Types There are three types of meta-SQL elements: Construct Constructs are a direct substitution of a value, and help to build or modify a SQL statement. Examples include %Bind, %InsertSelect, and %List. Function Functions perform actions or cause another function to be called. Examples include %ClearCursor, %Execute, and %ExecuteEdits. Meta-variable. Meta-variables enable substitution of text within SQL statements. Examples include %AsOfDate, %Comma, and %JobInstance.

Meta-SQL Placement Considerations: Not all meta-SQL can be used by all programs. Some meta-SQL can be used only in Application Engine programs. Other meta-SQL can only be used as part of a SQL statement in a SQL or dynamic view. The following table lists available meta-SQL elements and where each element can be used. If a meta-SQL construct, function, or meta-variable is supported in PeopleCode, it is supported in all types of PeopleCode programs; that is, in Application Engine PeopleCode programs (actions), component interface PeopleCode programs, and so on. Note. Even if a meta-SQL element is used in PeopleCode, you cannot use meta-SQL like a built-in function. You can use meta-SQL in the SQLExec function, the Select method, the Fill method, and so on. Note. Meta-SQL is not available in SQR

Meta-SQL
One of the most useful development shortcuts in PeopleSoft is Meta-SQL. If you don't know about Meta-SQL then this example of how to refactor standard SQL to Meta-SQL should help you get an idea of what it can do.

The Example - PeopleTools SQL Definition Data

In this example, the following tables are used to return information about stored PeopleTools SQL definitions: Description PSSQLDEFN SQL Definitions SQL Definition Text - Actual PSSQLTEXTDEFN Stored SQL Table Key Fields
SQLID, SQLTYPE SQLID, SQLTYPE, MARKET, DBTYPE, EFFDT, SEQNUM

Here's how you might write a query that joins these records to give you the latest effective dated unique fields from these tables:
select S.SQLID, S.SQLTYPE, S.VERSION, S.LASTUPDOPRID, S.LASTUPDDTTM, S.ENABLEEFFDT, S.OBJECTOWNERID, ST.MARKET, ST.DBTYPE, ST.EFFDT, ST.SEQNUM, ST.SQLTEXT from PSSQLDEFN S, PSSQLTEXTDEFN ST where ST.SQLID = S.SQLID and ST.SQLTYPE = S.SQLTYPE and ST.EFFDT = ( select max(EFFDT) from PSSQLTEXTDEFN where SQLID = ST.SQLID and SQLTYPE = ST.SQLTYPE and MARKET = ST.MARKET and DBTYPE = ST.DBTYPE and SEQNUM = ST.SEQNUM and EFFDT <= sysdate ) ;

Note that the SEQNUM field is used to partition long SQL statements. If you have a SQLID with a SEQNUM greater than 0, it is because it is too long to fit in one row for the SQLTEXT long field. Since you would want to return all SEQNUM rows, there is no need to add any conditions for SEQNUM in the query above.

Refactoring with Meta-SQL


The refactoring steps for the above SQL statement include: Replacing the hard coded database table names with %Table and the PeopleSoft record definition names Using %Join to perform the join on common keys between PSSQLDEFN and
PSSQLTEXTDEFN

Replacing the effective date logic with %EffdtCheck

Here's how the Meta-SQL looks after these changes:


SELECT S.SQLID , S.SQLTYPE , S.VERSION , S.LASTUPDOPRID , S.LASTUPDDTTM , S.ENABLEEFFDT , S.OBJECTOWNERID , ST.MARKET , ST.DBTYPE , ST.EFFDT , ST.SEQNUM , ST.SQLTEXT FROM %Table(PSSQLDEFN) S , %Table(PSSQLTEXTDEFN) ST WHERE %Join(COMMON_KEYS, PSSQLDEFN S, PSSQLTEXTDEFN ST) AND %EffdtCheck(PSSQLTEXTDEFN ST_ED, ST, %CurrentDateTimeIn)

Hide the resolved Meta-SQL


SELECT S.SQLID , S.SQLTYPE , S.VERSION , S.LASTUPDOPRID , S.LASTUPDDTTM , S.ENABLEEFFDT , S.OBJECTOWNERID , ST.MARKET , ST.DBTYPE , ST.EFFDT , ST.SEQNUM , ST.SQLTEXT FROM PSSQLDEFN S , PSSQLTEXTDEFN ST WHERE S.SQLID = ST.SQLID AND S.SQLTYPE = ST.SQLTYPE AND ST.EFFDT=( SELECT MAX(EFFDT) FROM PSSQLTEXTDEFN ST_ED WHERE ST_ED.SQLID=ST.SQLID AND ST_ED.SQLTYPE=ST.SQLTYPE AND ST_ED.MARKET=ST.MARKET AND ST_ED.DBTYPE=ST.DBTYPE AND ST_ED.SEQNUM=ST.SEQNUM AND ST_ED.EFFDT<=SYSDATE)

Note that because we are selecting fields from more than one table (and not all the fields), the %SelectAll construct is not going to work in this case.

Thoughts on using Meta-SQL


Meta-SQL isn't a silver bullet. There are legitimate cases when you shouldn't use it because it simply can't do what you want or because it does it poorly (e.g. performance). In terms of aesthetics, Meta-SQL doesn't support ANSL SQL join syntax, however the benefits of using Meta-SQL usually outweigh the aesthetic costs.

There are a few Meta-SQL conventions that you should always try to use:

The relevant Meta-SQL date and time functions constructs The %Table construct with record names instead of database table names. See this article about why you should be doing this. Essentially, like the other Meta-SQL constructs it reduces the impact of changes to the system to your code.

Remember to always resolve your Meta-SQL to verify that it creates the correct SQL statement for your database platform.

%SelectAll
If you ever need to create a view that selects all fields from a particular record, then you should be using the %SelectAll meta-sql construct. Why? Because %SelectAll uses the underlying record definition to select the fields - so it will always return all fields from the underlying record, even if that record definition changes. The basic syntax is:
%SelectAll(RECORD_NAME ALIAS)

There is all a %SelectDistinct construct which adds a distinct to the select clause and uses the same syntax.
%SelectAll

returns all the fields for the record specified and includes from clause.

For example, say I want the latest effective dated, active fields from PSXLATITEM. My SQL might start something like this:
select FIELDNAME, FIELDVALUE, EFFDT, EFF_STATUS, XLATLONGNAME, XLATSHORTNAME, LASTUPDDTTM, LASTUPDOPRID, SYNCID from PSXLATITEM A where EFFDT = ( select max(EFFDT) from PSXLATITEM where FIELDNAME = A.FIELDNAME and FIELDVALUE = A.FIELDVALUE and A.EFFDT <= sysdate ) and A.EFF_STATUS = 'A' ;

Instead of typing out all those fields, lets use %SelectAll - that's what I did to generate this example btw ;)

So our meta-sql would look like this - (I've also replaced sysdate with %CurrentDateIn)
%SelectAll(PSXLATITEM A) where EFFDT = ( select max(EFFDT) from PSXLATITEM where FIELDNAME = A.FIELDNAME and FIELDVALUE = A.FIELDVALUE and A.EFFDT <= %CurrentDateIn ) and A.EFF_STATUS = 'A'

Note that %SelectAll wraps date, time and date/time fields with %DateOut, %TimeOut, %DateTimeOut as well. This resolves into the following meta-sql:
SELECT A.FIELDNAME , A.FIELDVALUE , TO_CHAR(A.EFFDT ,'YYYY-MM-DD') , A.EFF_STATUS , A.XLATLONGNAME , A.XLATSHORTNAME , TO_CHAR(A.LASTUPDDTTM ,'YYYY-MM-DD-HH24.MI.SS."000000"') , A.LASTUPDOPRID , A.SYNCID FROM PSXLATITEM A WHERE EFFDT = ( SELECT MAX(EFFDT) FROM PSXLATITEM WHERE FIELDNAME = A.FIELDNAME AND FIELDVALUE = A.FIELDVALUE AND A.EFFDT <= TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-DD'),'YYYY-MM-DD') ) AND A.EFF_STATUS = 'A'

Note that the example includes an alias of A in the parameters to %SelectAll. If you are using %SelectAll you might have to play with your SQL a bit to get it work, especially if you are using joins to other tables. It may not work in all cases, but if nothing else, its a time saver!

%EffdtCheck
There is a meta-sql element called %EffdtCheck which writes effective date logic for you. For example, I'm writing a view that returns the maximum effective dated and active subject from the subject table. Here's the meta-SQL:
SELECT INSTITUTION , SUBJECT , DESCR , ACAD_ORG , DESCRFORMAL FROM PS_SUBJECT_TBL SUBJ WHERE %EffdtCheck(SUBJECT_TBL SUBJ_ED, SUBJ, %CurrentDateIn)

AND SUBJ.EFF_STATUS = 'A'

The line %EffdtCheck(SUBJECT_TBL SUBJ_ED, SUBJ, %CurrentDateIn) expands to get the maximum effective date from the subject table joining on the keys where the effective date is less than or equal to %CurrentDateIn (or whatever date you decide). Note that SUBJ_ED is the alias to the table used for the effective dated join. The second parameter, SUBJ is the alias of the root table. %EffdtDtCheck doesn't include effective sequence or effective status logic so you'll still have to write that the old fashioned way. To check your sql, use the resolve meta-sql functionality in application designer. So why bother doing this? Well, if the structure of the base table changes and there is a new key, the Meta-SQL will automatically adjust to include the new key. This means you don't have to update the view SQL. It also eliminates the possiblity of missing out joins on keys when you write your effective date logic. Have a look in PeopleBooks for further info. There are a lot of really useful meta-sql elements, just search on meta-sql in the PeopleCode Language reference PeopleBook. If you use this with the Rowset Fill method, the table alias (parameter 2) is just FILL. This is the alias given automatically PeopleSoft where expanding the SQL in the Fill statement.

Limitations Of %EffDtCheck
The %EffDtCheck construct expands into an effective date subquery suitable for a Where clause. However, it cannot be used with records that contain EFFSEQ as part of the key in that case, the %EffDtCheck construct is expanded into an effective date subquery INCLUDING the EFFSEQ in the join criteria - which is wrong! For example, the following SQL:
SELECT * FROM PS_JOB JOB WHERE EMPLID = :1 AND EMPL_RCD = :2 AND %EffdtCheck(JOB, JOB_ES, %CurrentDateIn)

Expands into:
SELECT * FROM PS_JOB JOB WHERE EMPLID = :1 AND EMPL_RCD = :2 AND JOB_ES.EFFDT=( SELECT MAX(EFFDT) FROM PS_JOB JOB WHERE JOB.EMPLID=JOB_ES.EMPLID AND JOB.EMPL_RCD=JOB_ES.EMPL_RCD AND JOB.EFFSEQ=JOB_ES.EFFSEQ /* this shouldn't be used in EFFDT subquery */ AND JOB.EFFDT<=TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-DD'),'YYYY-MM-DD'))

As such, when retrieving the current effective row for a record with EFFSEQ as part of the key, the %EffDtCheck construct should not be used. This also applies to other records that contain EFFDT field + additional fields after EFFDT that indicate a parent-child

relationship. As stated above, the %EffDtCheck Meta-SQL uses all keys when it's expanded - which may not be what you want in all cases. Furthermore, as stated above, if the structure of the base table changes and there is a new key, the Meta-SQL will automatically adjust to include the new key. Once again, this may not be the desired behaviour in certain cases.

Date and Time in Meta-SQL


Similar to the article on date and time in PeopleCode this article covers working with date and time in Meta-SQL. The Meta-SQL date/time constructs you should know about are: For input/output of the current date/time:
%CurrentDateIn %CurrentDateOut %CurrentDateTimeIn %CurrentDateTimeOut %CurrentTimeIn %CurrentTimeOut

For input/output of any date/time:


%DateIn %DateOut %DateTimeIn %DateTimeOut %TimeIn %TimeOut

Remember that:

input date/time goes in the WHERE clause (conditions) output date/time goes in the SELECT clause (returned data)
%DateNull %DateTimeNull %TimeNull

For input/output of a null date/time:

For getting part of a date/time:


%DatePart %TimePart

gets the date gets the time

For date arithmetic: gives the resulting date. You can use negative numbers to get a past date. So this is also the DateSubtract function. %DateDiff(from, to) gives the difference between two dates in days %DateTimeDiff(from, to) gives the difference between two date/times in minutes
%DateAdd(from, days_to_add)

Date and Time in PeopleCode

Setting a Date to Null in PeopleCode


To set a date to null in PeopleCode either use the SetDefault() function (deprecated) or the SetDefault field method Using the function:
SetDefault(YOUR_RECORD.DT_FIELD);

Using the field method if you are in the current context:


YOUR_RECORD.DT_FIELD.SetDefault();

Using the field method if you are not in the current context using a field object:
Local Field &fldDateExample; /* Code to set your &fldDateExample object */ &fldDateExample.SetDefault();

Not intuitive but it works.

Setting a Date to Null in PeopleCode (Part II another way!)


There is also another way to set a date to null via PeopleCode! In some cases, using SetDefault() to blank out a field is not what we're after, as there may be a default for the field! The only other way (to my knowledge) is this:
RECNAME.DATE_FIELD.Value = "";

.Value is the KEY here. Not including .Value will throw Syntax errors in App Designer when you try to assign the date field to "" and save your program.

Getting the time in the format HHMMSS from the current time:
Getting time in the format HHMMSS from the current time:
Local &strCurrentTime; &strCurrentTime = Substring(Substitute(String(TimePart(%Datetime)), ".", ""), 1, 6);

This takes the time part of the current date time on the application server, replaces the dot (.) seperators with blanks, and returns only the first 6 characters (hhmmss) ignoring the millisecond part. This returns say a time of 11.52.00.000000 as 115200. I used this in an application to rename a file with a date & time stamp.

Use %DateOut to Get Dates from SQL into a Date Variable


If you are using a date that is returned from SQL and storing it into a date variable, make sure you wrap your date with %DateOut in your SQL, otherwise PeopleSoft will throw an invalid date error.

Você também pode gostar