I'm trying to write a SQL script for use in SQL plus using substitution variables defined at runtime. Is there a way to actively escape any special characters coming in?
For instance, if the variable has an ' in it, it will immediately break whatever line in the script is running it with a
ORA-01756: quoted string not properly terminated
error since I didn't complete the quote or completed it too early. I just want it to treat the variable as a string. Is there a way to tell Oracle to just treat the characters literally to set a field or similar?
In my specific case, I want to make a general case script to change a password by prompting for the user, old, and new password.
connect &&myuser/&&oldpass#mydb;
alter user &&myuser identified by &&newpass replace &&oldpass;
If the old or new password contains special characters, it could break for a plethora of reasons, including the issue I have above.
No, there is no way to escape characters in substitution variable values.
SQL*Plus substitution variables (those of type CHAR, the only other types are numeric) are always substituted verbatim. SQL*Plus pays no attention to the structure of the statements in which substitution variables appear: it just does a search-and-replace of the variables with their values, irrespective of whether doing that leaves a valid SQL statement afterwards.
Related
I'm trying to add some constraints on database creation command in PostgreSQL.
Currently, I could do
psql -c "CREATE database \" x y\"\"z' \""
Then, I will get a database named literally " x y"z' " (without the double-quotes boundary).
It seems that pgsql supports any characters in it's database name, which is cool.
But it leads me headaches when I am doing automation stuff with bash script.
Yes, some additional work could be done to handle these cases in script. But I think these kind of names are actually meaningless (at least in my situation :), so, is there a way to add some constraints on database naming. For example, only allow [a-zA-Z0-9_.]+.
Just do not use double quotes, which you should avoid anyway if at all possible. See Documentation:
SQL identifiers and key words must begin with a letter (a-z, but also
letters with diacritical marks and non-Latin letters) or an underscore
(_). Subsequent characters in an identifier or key word can be
letters, underscores, digits (0-9), or dollar signs ($). Note that
dollar signs are not allowed in identifiers according to the letter of
the SQL standard, so their use might render applications less
portable. The SQL standard will not define a key word that contains
digits or starts or ends with an underscore, so identifiers of this
form are safe against possible conflict with future extensions of the
standard. ... There is a second kind of identifier: the delimited
identifier or quoted identifier. It is formed by enclosing an
arbitrary sequence of characters in double-quotes ("). A delimited
identifier is always an identifier, never a key word. ... Quoted
identifiers can contain any character, except the character with code
zero. (To include a double quote, write two double quotes.) This
allows constructing table or column names that would otherwise not be
possible, such as ones containing spaces or ampersands.
Not doubling quoting in you examples makes those names invalid and Postgres has no problem telling about it. So just do not use them.
Alternately you could create an event trigger. Within there you can restrict object names as needed, esp useful if you have strict naming standards. This would allow for database enforcement of those standards;
create function app_validate_table_name()
returns event_trigger
language 'plpgsql'
as $$
begin
if obj.object_identity ~! '[A-Za-z$_][[A-Za-z0-9$_]{0,62}'
then
raise exception 'App Error: Request Name (%) is invalid for <Your App Name here>',obj.object_identity;
end if
return;
end ;
$$;
create event trigger app_table_event_trigger on ddl_command_end
when tag in ('ALTER TABLE', 'CREATE TABLE')
execute procedure app_validate_table_name();
While the same can be applied to other objects it unfortunately does not seem to apply to creating a database itself.
Disclamer: The above has NOT been tested.
For a gradle script, I am composing strings that will be used as command line for a subsequent gradle Test-task. One of the strings is the user's password, which eventually will be passed to the called (exec'ed) "java ..." call using the JVM's -D option, e.g. -Dpassword=foobar.
What complicates things here is, that this password can/should of course contain special characters, that may interfere with the use of the string as command line. In other words: I need to escape special characters (which is OS-specific). :-(
Now to my actual question:
I want to use the String.replaceAll method, i.e. replaceAll(list_of_special characters, EscapeCharacter + Ref_to_matched_character),
e.g. simplified something like replaceAll("[#$%^&]", "^$1")
'^' meaning the escape character and '$1' meaning the matched character here.
Is that possible, i.e. can one refer to the matched pattern in the second argument of replaceAll?
Is that possible, i.e. can one refer to the matched pattern in the second argument of replaceAll?
yes, it's possible
'a#b$c'.replaceAll('([#$%^&])', '^$1')
returns
a^#b^$c
Thanks for the responses and the reviews improving readability. Meanwhile I got my expression working. For those interested:
// handles gthe following: `~!##$%^&*()_+-={}|[]\:;"'<>?,./
escaped = original.replaceAll('[~!##\\$\\%\\^\\&\\*\\(\\)_\\+-={}\\|\\[\\]\\\\:;\"\\\'<>\\?,\\./]', '^$0') // for Windows - cmd.exe
I have a script I'm trying to run via sqlplus. At the top of the script, I have "SET DEFINE OFF" set. However, when I run it, I'm receiving this error:
SP2-0552: Bind variable "CHANDAWALA" not declared.
I believe this is happening because I have a couple update statements that include colons within a string like this:
UPDATE ADDRESS SET ADDRESS_STREET_LINE1 = 'Moh: Chandawala'...
UPDATE ADDRESS SET ADDRESS_STREET_LINE1 = 'Moh:chandawala'...
So it's treating them like bind variables. I was under the impression that SET DEFINE OFF would make it treat anything within a quoted string as characters and not interpret anything within, including perceived bind variables.
This obviously isn't the case - So in this situation, what am I supposed to do? Do I have to escape these manually?
Thanks.
EDIT - The posted question at When or Why to use a "SET DEFINE OFF" in Oracle Database doesn't help me since that person is trying to escape ampersands for variable substitution, and not colons as bind variables. I'm looking for a way to tell the client to ignore anything (including colons) in quoted strings.
EDIT - Okay, so it sounds like Oracle shouldn't be interpreting that as a bind variable within quotes. So now the question is, why is it doing that?
Set Define Off is a SQLPlus command and it prevents SQLPlus from treating & as a special character. & is also specific to SQLPlus and have no meaning outside it.
When define is on, the SQLPlus replaces the substitution variables with actual values and then pass it to the Oracle SQL engine.
On the other hand, : are real bind variable that only Oracle SQL engine recognises and look for a to-be-bound value. The : are not recognized as bind meta character by SQLPlus and is passed as such to the SQL engine.
I cannot duplicate your issue. I created a table called dually with a column of a single character. When I attempt to run the update statement, no substitution is permitted.
SQL> UPDATE brianl.dually
2 SET dummy = ':x';
SET dummy = ':x'
*
ERROR at line 2:
ORA-12899: value too large for column "BRIANL"."DUALLY"."DUMMY" (actual: 2,
maximum: 1)
Have you tried using concatenation?
UPDATE ADDRESS SET ADDRESS_STREET_LINE1 = 'Moh' || ':' || Chandawala'
I'm working with a batch file and I was wondering, why do some variables have double quotes around them and others don't, for example?
SET "keePass=%USERPROFILE%\KeePass\KeePass-2.31\KeePass.exe"
but this:
SET name="bob"
Why the double quotes in the first one, but not the second?
...to provide the conclusion at the beginning:
Supposing you have got the command extensions enabled (which is the default setting of the Windows command prompt cmd), the best practice is to use the following set syntax:
set "VAR=value"
(The command extensions can be enabled/disabled by cmd (type cmd /? in a command prompt window for help) or, within batch files only, by setlocal (type setlocal /? for details).)
At first, let us take a look at the standard syntax mentioned in the help text, that appears when typing set /? (or help set) in a command prompt window:
set VAR=value
This assigns the string value to the variable VAR obviously.
The good thing of this syntax is:
it also works when the command extensions are disabled;
the variable value is not surrounded by quotation marks (supposing value does not contain such on its own), so there is only one place to take care of them, namely during variable expansion (like %VAR% or "%VAR%", depending on the situation at hand; this is particularly useful when combining strings like constant_%VAR% or "constant_%VAR%", which will be expanded to constant_value or "constant_value", respectively, so you always have full control over the placement of the quotation marks; if the value contained the enclosing "", constant_%VAR% would expand to constant_"value", which might probably not be the string you want to have);
But there might occur some problems:
any (invisible) trailing white-space becomes part of the string value, so if the command line is followed by a single SPACE character, VAR will carry the value valueSPACE;
when you concatenate this command with another command, like set VAR=value & echo Text, the SPACE before the & character becomes part of the value; you could of course write set VAR=value&echo Some text, but this was quite difficult to read;
if value contains special characters, like ^ & ( ) < > |, you might run into problems; for example, set VAR=1&2 will assign 1 to VAR, then an error will arise, because & separates two commands and 2 is not a valid one;
The syntax of the second example in your question is quite similar:
set VAR="value"
This assigns the string "value" to VAR, so the quotation marks are included in the value.
The advantages are:
it also works when the command extensions are disabled;
special characters (like ^ & etc.) in value do not cause any trouble because of the "";
But still:
the quotation marks become part of the value, which may be disturbing in numerous situations;
unwanted trailing white-spaces (after the last ") still become part of the string value;
again when concatenating this command with another command using &, you have to omit spaces around the ampersand;
Now, let us check out the syntax of the first example in your question:
set "VAR=value"
This assigns value to VAR. Since the quotation marks are placed around the entire assignment expression, they are removed before the assignment is actually accomplished.
This has got several advantages:
the quotation marks do not become part of the variable value;
any (unintended) trailing white-spaces do not become part of the variable value;
you can concatenate it with another command using SPACE&SPACE without any unwanted spaces being appended to the value;
special characters (like ^ & etc.) in value are no problem;
But there is one issue:
the command extensions need to be enabled for this syntax to work; otherwise, an error arises;
Finally, you could also combine the above syntaxes, if you do want the quotation marks to become part of the variable value (although I do not recommend that):
set "VAR="value""
This assigns "value" to VAR.
Advantages:
unwanted trailing white-spaces (after the last ") do not become part of the variable value;
you can concatenate it with another command using SPACE&SPACE without any unwanted trailing spaces in the value;
Disadvantages:
the quotation marks become part of the value, which may be disturbing in numerous situations;
the command extensions need to be enabled for this syntax to work; otherwise, an error arises;
special characters (like ^ & etc.) in value may cause problems; this is because of the way the command parser works: as soon as the first " is encountered, any special characters are no longer recognised, they are treated as literal characters; after the next ", special character recognition becomes re-activated, and so on; regard that this is also true in case value itself contains any quotation marks on its own;
Side Note:
Never put spaces around the equal-to sign in a set command line, because they will become part of the variable name and/or value. For instance, the command lines
set VAR = value
and
set "VAR = value"
both assign the string value SPACEvalue to a variable named VARSPACE.
I'm attempting to generate a url using a bunch of different variables however when I follow a variable with an underscore the variable after the underscore does not show up. However, if I put a space before the underscore then there is a space in the generated URL. So my question is, is there an escape character for doing the sort of thing I have described?
Also code:
URL="$baseURL$BUILD/TorBrowserBundle-$BUILD-$OS$BIT _$LANG.zip"
The issue occurs in between $BIT and $LANG.
you can use ${}
so something like
URL="${baseURL}${BUILD}/TorBrowserBundle-${BUILD}-${OS}${BIT}_${LANG}.zip"