Batch file: escape a % character into a PostgreSQL query - sql

I need to use a % character into a SQL query that I pass into a windows batch file. My issue is that this character is not taken into account.
towns=(12232, 12233)
for %%a in %towns% do (
"C:\Program Files\PostgreSQL\9.4\bin\pgsql2shp.exe" -h localhost -u thomas -P password thomas_db "SELECT * FROM schema.table WHERE code like '%%a%'"
)
I get the following error:
C:\batch><"C:\Program Files\PostgreSQL\9.4\bin\pgsql2shp.exe" -h localhost -u thomas -P password thomas_db "SELECT * FROM schema.table WHERE code like '12232'">
Initializing...
ERROR: Could not determine table metadata
The LIKE '%%a%' is interpreted as LIKE '12232' and should be as LIKE '12232%'.

A double percent escapes a percent so double it up:
... WHERE code like '%%a%%%'"

Related

Query working fine on PGAdmin but not on Terminal

I am planning to create a cronjob that will change the password of my site every 15th day of the month. This is my .sh file
psql -U postgres -h (sample-host) (sample-db) -p (sample-port) -c "UPDATE web_user SET password_hash = '$2a$12$ohJ0j2Y9lRkO6Ld9MaiLuu7Q4hzYSr1IsM5SfY1SxAGk6fgn20aj2' WHERE email = 'email#email.com'"
When i run the query UPDATE web_user SET password_hash ='$2a$12$ohJ0j2Y9lRkO6Ld9MaiLuu7Q4hzYSr1IsM5SfY1SxAGk6fgn20aj2' WHERE email = 'email#email.com'; on pgadmin, everything is fine. The update is fine and the password is right. But when I run my .sh file on my machine(ubuntu 18.04), and even manually running it on the terminal, the result will be just a.
There are no errors messages or anything like that. Is there something that I missed? BTW the version of is postgresql 13.4.
Update: I just found out that special characters are causing the problem. it seems that the psql command does not allow special characters. The problem is I can't find any resources about these things.
For the special characters you need to a workaround
I tried in powershell, may be work in linux terminal
before:
postgres=# select * from web_user;
pass | email
------+-------
(0 rows)
used echo to output the password_hash as it contains special characters.
psql -U postgres -h localhost -d postgres -p 5432 -c "UPDATE web_user SET pass = '$(echo '$2a$12$ohJ0j2Y9lRkO6Ld9MaiLuu7Q4hzYSr1IsM5SfY1SxAGk6fgn20aj2')' WHERE email = 'email#email.com'"
output:
postgres=# select * from web_user;
pass | email
--------------------------------------------------------------+-----------------
$2a$12$ohJ0j2Y9lRkO6Ld9MaiLuu7Q4hzYSr1IsM5SfY1SxAGk6fgn20aj2 | email#email.com
(1 row)

SQLCMD use LIKE '%#%'

I'm trying to run a query using SQLCMD.EXE and have trouble with the LIKE portion.
WHERE email LIKE '%%#%%'
I think it is an error with cmd prompt rather then SQLCMD.EXE since I get the error:
Syntax error "#%'"
I am running this via Notepad++ (NppExec) pointing to the bat file like so:
H:\scripts\SQL.bat "$(CURRENT_WORD)"
This causes the query to be wrapped in double quotes before being used by the SQLCMD.EXE call. The SQLCMD.EXE call then runs in the bat file like so:
SQLCMD.EXE -U user -P %pass% -S %server% -Q %sql% -d %table%
It works perfect on any query I use aside from this LIKE '%%#%%' part.
UPDATE
I've done a few more tests and think I have narrowed it down to being a problem with the % and the #.
So queries like these work fine:
SELECT name FROM table WHERE name LIKE 'test'
SELECT name FROM table WHERE name LIKE 'test%'
SELECT name FROM table WHERE name LIKE '%%test'
But these will cause errors:
SELECT name FROM table WHERE name LIKE '%test'
SELECT name FROM table WHERE name LIKE '%test%'
This is fine since I am ok with doubling the % in my queries, but I've tried %%#% and %%#%% and they throw errors. Syntax error "#'"" or Syntax error "#%'"", respectively.
Also, the reason for the variables is that I included some logic so it can detect table names and run for different servers and databases.
Here is the bat file
set sql=%1
iff %#index[%sql%,sur_] GT -1 THEN
SET SERVER=server1
SET table=tablename
SET pass=password
else
SET SERVER=server2
SET table=tablename
SET pass=password
endiff
SQLCMD.EXE -U usr -P %pass% -S %server% -Q %sql% -d %table%
The reason for the weird syntax is due to the command being run through TCC/LE (see here)
I'm not quite sure what your reasoning is for doubling up the %s, but it looks like your intent is to find values in the email column that contain #. If so, you can try rewriting the clause as such:
WHERE CHARINDEX('#', email) > 0
If it's the # symbol that is tripping things up, use CHAR(64) instead.
WHERE CHARINDEX(CHAR(64), email) > 0
When run query with sqlcmd, i found that % symbol will be removed. Let's say your query is :
SELECT name FROM table WHERE name LIKE 'test%'
The sqlcmd will read your query as
SELECT name FROM table WHERE name LIKE 'test'
So sqlcmd will not filter your result. Please use %% for query
SELECT name FROM table WHERE name LIKE 'test%%'
and you will get result
SELECT name FROM table WHERE name LIKE 'test%'
I have tested this on SQLServer 2005 & 2008

How to escape apostrophe in a db2 sql query, running within a shell script?

I'm trying run a query that will include static columns in its output. The select statement works when I run it via the CLP, but not when I execute it within a shell script:
su - myid -c 'db2 connect to mydb;db2 -x -v "select COL1,'','',COL2,'','',COL3L from MYTABLE fetch first 10 rows only"; db2 connect reset;'
When I run this, the output error I get is:
SQL0104N An unexpected token "," was found following "select COL1,".
Expected tokens may include: "<select_sublist>". SQLSTATE=42601
SQL1024N A database connection does not exist. SQLSTATE=08003
I've even tried putting the select statement in a variable and inserting that within the statement, but still the same error. Any help would be greatly appreciated. -Thx
You should escape the single quotes as with a backlash as in :
su - myid -c 'db2 connect to mydb;db2 -x -v "select COL1,\'\',\'\',COL2,\'\',\'\',COL3L from MYTABLE fetch first 10 rows only"; db2 connect reset;'
Beware, I didn't test it... no shell at hand just now.
UPDATE:
Finally I got my hands on a DB2 instance.. after a little testing i got it working.
It turns out that the previous syntax was faulty. The proper way of quoting the single quote is (in this case) '\'' as in:
su - myid -c 'db2 connect to mydb;db2 -x -v "select COL1,'\'','\'',COL2,'\'','\'',COL3L from MYTABLE fetch first 10 rows only"; db2 connect reset;'
That's because the single quote around the whole command must be closed (') in order to supply the escape for the single quote in the db2 query (\') and then reopened to resume the command quoting ('). Weird as it looks, it works....
This is the command I used to test it:
bash -c 'db2 connect to mydb;db2 -x -v "select 1,'\'','\'',2,'\'','\'',3 from SYSIBM.SYSDUMMY1 fetch first 10 rows only"; db2 connect reset;'

SQLCMD Incorrect syntax near '.'

When executing a stored procedure using SQLCMD with the following parameters:
. sqlcmd -S $sql_server -U $sql_usr -P $sql_pwd -d $sql_db -Q "EXEC $storedProc $dateVariable, $regionType, ALM.10.2.33.1" -V 1 -b
The following message is received:
Incorrect syntax near '.'.
If I pass ALM_10_2_33_1 instead of ALM.10.2.33.1, the stored procedure is executed perfectly.
Thanks,
Delimit the parameter correctly with single quotes
"EXEC $storedProc $dateVariable, $regionType, 'ALM.10.2.33.1'"
SQL Server has quirk that allows (var)char parameters to be specified without delimiters if they don't contain certain characters like ..
You can see it in MSDN
EXEC sp_addserver <'new_name\instancename'>, local
But if you check sp_addserver, #local is varchar(10), and 'LOCAL' is mentioned as the value required.
Try wrapping ALM.10.2.33.1 in square brackets:
[ALM.10.2.33.1]

Return a scalar query result into a batch file variable

I would like to perform a scalar database query and return the result into a variable in a batch file.
How would one do this? The closest I example in our system that I see is if I return an exit code based on a scalar query result.
Z:\SQL2005\90\Tools\Binn\sqlcmd -S servername -dCLASS -E -Q "EXIT(select case run_type when 'Q' then 200 else 100 end from cycle_date where cycle = '1')">NUL
if %errorlevel% == 200 call %SQLSERVER%
QRTLY.BAT
if %errorlevel% == 100 call %SQLSERVER%
MTHLY.BAT
Can someone help me with the syntax?
Here's some sqlcmd help info:
-v var = value[ var=value...]
Creates a sqlcmdscripting variable that can be used in a sqlcmd script. Enclose the value in quotation marks if the value contains spaces. You can specify multiple var="values" values. If there are errors in any of the values specified, sqlcmd generates an error message and then exits.
sqlcmd -v MyVar1=something MyVar2="some thing"
sqlcmd -v MyVar1=something -v MyVar2="some thing"
-x disable variable substitution
Causes sqlcmd to ignore scripting variables. This is useful when a script contains many INSERT statements that may contain strings that have the same format as regular variables, such as $(variable_name).
How about saving it to a file without headers then reading the contents back in?
sqlcmd -S(local)\SQLExpress -dMyDatabase -Umyuser -Pmypassword -W -h -1 -Q "SELECT Top 1 MyValue FROM MyTable" -o sqlcmdoutput.txt
set /p x= <sqlcmdoutput.txt
del sqlcmdoutput.txt
echo My scalar value is %x%
I use this in a batch file. It returns the LogicalFilename for a SQL Server Database data file. This only works if there is one data file in the DB.
So the result is the environment variable DATABASEFILENAME is set to say AdventureWorks_Data.
FOR /F "usebackq tokens=1" %%i IN (`sqlcmd -w200 -h-1 -E -Q"set nocount on; Select df.name From sysdatabases as d Inner Join sysaltfiles as df on d.dbid=df.dbid Where d.name ='$(DatabaseName)' and df.Fileid =1"`) DO set DATABASEFILENAME=%%i
Have you looked at sqlcmd?