Within sqlplus a good number of parameters exist that can be set at the session level through the ‘set’ command. These parameters include arraysize, autocommit, autotrace, echo and linesize which affect how results are displayed and whether or not to require the commit instruction to preserve changes, nothing unusual here. There is one parameter that is most often ignored or forgotten: define. By default the value is set to ‘&’, but it can be set to almost any character one could desire. What define does is tell sqlplus how variables are, well, defined, that is, how sqlplus will identify what a variable is. That may be a bit confusing so let’s look at define a bit closer.
As already mentioned define is set to the ‘&’ character; this is the first character in variable names that sqlplus will use to so that sqlplus will take the assigned value rather than the literal text of the variable name. As a basic example the column command can use the new_value function to assign a variable to a returned column in a query:
column sysdate new_value sys_dt noprint
The above command will assign the variable name to the SYSDATE column when it is returned in a query result; additionally the column will NOT be printed as output from the query itself. Since define has not been altered it remains set to ‘&’, and the value of SYSDATE can be accessed using the following construct:
&sys_dt
Providing a working example as an llustration produces:
SQL> column sysdate new_value sys_dt noprint
SQL>
SQL> select sysdate from dual;
SQL> select ‘&sys_dt’ from dual
2 /
old 1: select ‘&sys_dt’ from dual
new 1: select ’28-MAR-22′ from dual
’28-MAR-2
28-MAR-22
SQL>
[The old and new output is because the verify parameter is set to ‘ON’; setting this to ‘OFF’ disables this output so spool files aren’t cluttered with these notifications:
SQL> set verify off
SQL> select ‘#sys_dt’ from dual;
’28-MAR-2
28-MAR-22
SQL>
When executing scripts or commands interactively having verify on can be helpful; when cron or other schedulers are executing SQL code it might be better to set verify off.]
Using this method a constant value for the variable can be set and passed throughout a SQL script, regardless of the script length, which can be very useful for generating report names and/or headers. However the default ‘&’ character can get ‘in the way’ when the & is used for other purposes, such as a special character in passwords. Regardless of the punctuation the & will be interpreted as a variable name for all text immediately after the & appears, producing some unexpected results:
SQL> create user obnopper identified by “A924857&882er0!”;
Enter value for 882er0:
Simply hitting the Enter/Return key can result in the command failing due to password verification failures or a password far shorter than expected:
SQL> create user obnopper identified by “A924857&882er0!”;
Enter value for 882er0:
old 1: create user obnopper identified by “A924857&882er0!”
new 1: create user obnopper identified by “A924857!”
User created.
SQL>
When automated scripts are used this behavior can, and will, result in login failures since the originally set password string is not the password finally set for the given user. This can be addressed in one of two ways:
- Set define off entirely
- Change the character define is set to use
Option #1 is great until you need to define a variable and use its value:
SQL> select ‘&sys_dt’ from dual;
old 1: select ‘&sys_dt’ from dual
new 1: select ’28-MAR-22′ from dual
’28-MAR-2
28-MAR-22
SQL> set define off
SQL> select ‘&sys_dt’ from dual;
‘&SYS_D
&sys_dt
SQL>
Now file names and report headers will be populated with the cryptic ‘&sys_dt’ string and multiple executions of a script across several days will all generate the same text, causing output files to be overwritten, which is not the desired result. Those not familiar with this behavior will find it odd that a date value is not present in a file name, especially when the ‘&’ character is used as the abbreviation for ‘and’:
set define off
ttitle ‘Profit & Loss Statement: ‘&sys_dt
Such report headers will, indeed, show ‘Profit & Loss Statement: ‘ but will include the &sys_dt string, rather than the date value it was assigned. One possible way around this is to use the CHR() function with the proper ASCII code for the &:
ttitle ‘Profit ‘||chr(38)||’ Loss Statement: ‘&sys_dt
Now, with define set at the default the header can still report ‘Profit & Loss Statement: ‘ and include the assigned value to &sys_dt. It could be a tedious task to modify every report header in this manner.
Option #2 is probably a better option, provided a character is selected that isn’t used for some other purpose elsewhere. There are some obvious choices to avoid:
| ( ) @ ! $
are all put to other uses in an Oracle database; ! and $ are used as shortcuts to escape to the operating system (! for UNIX/Linux, $ for Windows), @ is, obviously, the shortcut for the ‘run’ command for scripts, ( and ) are used within scripts to denote subqueries, in-lists, complex where clauses and as parameter delimiters for functions and procedures, among other uses. And the ‘|’ is used, in pairs, as a shortcut for concat(), so none of those characters would be good choices. There’s ‘?’, which sounds good until you realize that’s the shortcut for $ORACLE_HOME within sqlplus. Drat, drat and double drat.
There are still characters available, such as ‘#’, which might be the best option. Yes, ‘#’ is used as a comment character in shell scripts but its use in sqlplus should not be an issue. To set this fine character as the one to define variables:
SQL> set define ‘#’
SQL> show define
define “#” (hex 23)
SQL>
Now the sys_dt variable can be accessed using #sys_dt:
SQL> select ‘#sys_dt’ from dual;
old 1: select ‘#sys_dt’ from dual
new 1: select ’28-MAR-22′ from dual
’28-MAR-2
28-MAR-22
SQL>
and file names and report headers can again show the date, rather than the literal string. This setting persists for the duration of the sqlplus session or until another call to define changes the character; for scripts run through a scheduler simply exiting the session will undo the setting so that at the next login the default, ‘&’, is set. What convenience.
DEFINE may not be an oft-used parameter so the standard ‘&’ should work in most cases, but it is good to know how to change such settings should the need arise. Careful selection of the replacement character is the one important decision when changing this parameter value so that literal text and variable values can both appear in the same output, which allows report names and titles to include accurate and valid data, rather than obtuse variable names.
Definitions aren’t just found in a dictionary.