PostgreSQL \lo_import and how to get the resulting OID into an UPDATE command? - batch-file

I'm working with Postgres 9.0, and I have an application where I need to insert images into the remote server. So I use:
"C:\Program Files\PostgreSQL\9.0\bin\psql.exe" -h 192.168.1.12 -p 5432 -d myDB -U my_admin -c "\lo_import 'C://im/zzz4.jpg'";
where
192.168.1.12 is the IP address of the server system
5432 is the Port number
myDB is server database name
my_admin is the username
"\lo_import 'C://im/zzz4.jpg'" is the query that is fired.
After the image has been inserted into the database I need to update a row in a table like this:
UPDATE species
SET speciesimages=17755; -- OID from previous command.. how to get the OID ??
WHERE species='ACCOAA';
So my question is: how do I get the OID returned after the \lo_import in psql?
I tried running \lo_import 'C://im/zzz4.jpg' in Postgres but I get an error:
ERROR: syntax error at or near ""\lo_import 'C://im/zzz4.jpg'""
LINE 1: "\lo_import 'C://im/zzz4.jpg'"
I also tried this:
update species
set speciesimages=\lo_import 'C://im/zzz4.jpg'
where species='ACAAC04';
But I get this error:
ERROR: syntax error at or near "\"
LINE 2: set speciesimages=\lo_import 'C://im/zzz4.jpg'
^

As your file resides on your local machine and you want to import the blob to a remote server, you have two options:
1) Transfer the file to the server and use the server-side function:
UPDATE species
SET speciesimages = lo_import('/path/to/server-local/file/zzz4.jpg')
WHERE species = 'ACAAC04';
2) Use the psql meta-command like you have it.
But you cannot mix psql meta commands with SQL-commands, that's impossible.
Use the psql variable :LASTOID in an UPDATE command that you launch immediately after the \lo_import meta command in the same psql session:
UPDATE species
SET speciesimages = :LASTOID
WHERE species = 'ACAAC04';
To script that (works in Linux, I am not familiar with Windows shell scripting):
echo "\lo_import '/path/to/my/file/zzz4.jpg' \\\\ UPDATE species SET speciesimages = :LASTOID WHERE species = 'ACAAC04';" | \
psql -h 192.168.1.12 -p 5432 -d myDB -U my_admin
\\ is the separator meta-command. You need to double the \, in a "" string, because the shell interprets one layer.
\ before the newline is just the line continuation in Linux shells.
Alternative syntax (tested on Linux again):
psql -h 192.168.1.12 -p 5432 -d myDB -U my_admin << EOF
\lo_import '/path/to/my/file/zzz4.jpg'
UPDATE species
SET speciesimages = :LASTOID
WHERE species = 'ACAAC04';
EOF

After importing an image with this command:
\lo_import '$imagePath' '$imageName'
You can then find the description of the binary by querying the pg_catalog.pg_largeobject_metadata table which stores the oid value you need.
Ie:
"SELECT oid as `"ID`",
pg_catalog.obj_description(oid, 'pg_largeobject') as `"Description`"
FROM pg_catalog.pg_largeobject_metadata WHERE pg_catalog.obj_description(oid,'pg_largeobject') = '$image' limit 1 "

Here's how to do it if your field is type bytea.
\lo_import '/cygdrive/c/Users/Chloe/Downloads/Contract.pdf'
update contracts set contract = lo_get(:LASTOID) where id = 77;
Use \lo_list and \lo_unlink after you import.

Related

How to create a new local table from a select query on remote db in PostgreSQL?

I can use the following command to do so as long as I create the table and the appropriate columns first. I would like the command to be able to create table for me based on the results of my query.
psql -h remote.host -U myuser -p 5432 -d remotedb -c "copy (SELECT view.column FROM schema.view LIMIT 10) to stdout" | psql -h localhost -U localuser -d localdb -c "copy localtable from stdin"
Again, it will populate the data properly if I create the table and columns ahead of time, but it would be much easier if I could automate that with a comand that creates the table according to the results of my query.

Add a date to output filename using SQLCMD from within SQL Agent CmdExec?

I want to run a weekly extract from a SQL Server database using SQLCMD under SQL Agent. Because I need to save multiple extracts in the same share, I want to use the current date as part of the extract's file name. When doing this from the command line, I use:
sqlcmd -S POC -i "\\org-data\data\dept\share\registry\SQLCMD\extractdata.sql" -s "|" -W -h-1 -o "\\org-data\data\dept\share\registry\Extracts\extractdata.%date:~-4,4%%date:~-10,2%%date:~-7,2%.txt"
and it works perfectly.
When I place the same statement into a CmdExec under SQL Agent, my date becomes a syntax error -- ("The filename, directory name, or volume label syntax is incorrect")
How do others handle this? Thanks.
Try using the SQL Server Agent tokens. They are described in MSDN article, "Use Tokens in Job Steps". The DATE token provides the current date in YYYYMMDD format. For your example use:
"...\Extracts\extractdata.$(ESCAPE_DQUOTE(DATE)).txt"
This isn't working for me
echo off
sqlcmd -m 1 -S 10.108.96.210\QA832 -U Exception -P Password1 -i E:\KCM_UAT\Exception.sql -o C:\Test_$(ESCAPE_DQUOTE(DATE)).txt -W -h-1 -s " "
set /p delExit=Press the ENTER key to exit...:
The file is written out like this
Test_$(ESCAPE_DQUOTE(DATE)).txt

BCP when database name begins with a number

The name of our production database (created by a previous vendor) begins with numbers (e.g. 3717_databasename). As such, I keep getting the message "an error occurred while processing the command line" when trying to export the contents of a table. Here is my command:
bcp 3717_databasename..TableName out "C:\Temp\TableName.dat" -E -n -Slocalhost -Umyusername -Pmypassword
In such a scenario, the solution is to specify the database name separately with the "-d" switch, like so:
bcp TableName out "C:\Temp\TableName.dat" -E -n -Slocalhost -d3717_databasename -Umyusername -Pmypassword

How Do I Generate Sybase BCP Fmt file?

I have a huge database which I want to dump out using BCP and then load it up elsewhere. I have done quite a bit of research on the Sybase version of BCP (being more familiar with the MSSQL one) and I see how to USE an Import file but I can't figure out for the life of me how to create one.
I am currently making my Sybase bcp out files of data like this:
bcp mytester.dbo.XTABLE out XTABLE.bcp -U sa -P mypass -T -n
and trying to import them back in like this:
bcp mytester.dbo.XTABLE in XTABLE.bcp -E -n -S Sybase_157 -U sa -P SyAdmin
Right now, the IN part gives me an error about IDENTITY_INSERT regardless of if the table has an identity or not:
Server Message: Sybase157 - Msg 7756, Level 16, State 1: Cannot use
'SET IDENTITY_INSERT' for table 'mytester.dbo.XTABLE' because the
table does not have the identity property.
I have often used the great info on this page for help, but this is the first time i've put in a question, so i humbly request any guidance you all can provide :)
In your BCP in, the -E flag tells bcp to take identity column values from the input file. I would try running it without that flag. fmt files in Sybase are a bit finicky, and I would try to avoid if possible. So as long as your schemas are the same between your systems the following command should work:
bcp mytester.dbo.XTABLE in XTABLE.bcp -n -S Sybase_157 -U sa -P SyAdmin
Also, the -T flag on your bcp out seems odd. I know SQLServer -T is a security setting, but in Sybase it indicates the max size of a text or image column, and is followed by a number..e.g -T 32000 (would be 32Kbytes)
But to answer the question in your title, if you run bcp out interactively (without specifying -c,-n, or -f) it will step through each column, prompting for information. At the end it will ask if you want to create a format file, and allow you to specify the name of the file.
For reference, here is the syntax and available flags:
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc30191.1550/html/utility/X14951.htm
And the chapter in the Utility Guide:
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc30191.1550/html/utility/BABGCCIC.htm

Using variables in SQLCMD for Linux

I'm running the Microsoft SQLCMD tool for Linux (CTP 11.0.1720.0) on a Linux box (Red Hat Enterprise Server 5.3 tikanga) with Korn shell. The tool is properly configured, and works in all cases except when using scripting variables.
I have an SQL script, that looks like this.
SELECT COLUMN1 FROM TABLE WHERE COLUMN2 = '$(param1)';
And I'm running the sqlcmd command like this.
sqlcmd -S server -d database -U user -P pass -i input.sql -v param1="DUMMYVALUE"
When I execute the above command, I get the following error.
Sqlcmd: 'param1=DUMMYVALUE': Invalid argument. Enter '-?' for help.
Help lists the below syntax.
[-v var = "value"...]
Am I missing something here?
You don't need to pass variables to sqlcmd. It auto picks from your shell variables:
e.g.
export param1=DUMMYVALUE
sqlcmd -S $host -U $user -P $pwd -d $db -i input.sql
In the RTP version (11.0.1790.0), the -v switch does not appear in the list of parameters when executing sqlcmd -?. Apparently this option isn't supported under the Linux version of the tool.
As far as I can tell, importing parameter values from environment variables doesn't work either.
If you need a workaround, one way would be to concatenate one or more :setvar statements with the text file containing the commands you want to run into a new file, then execute the new file. Based on your example:
echo :setvar param1 DUMMYVALUE > param_input.sql
cat input.sql >> param_input.sql
sqlcmd -S server -d database -U user -P pass -i param_input.sql
You can export the variable in linux. After that you won't need to pass the variable in sqlcmd. However, I did notice you will need to change your sql script and remove the :setvar command if it doesn't have a default value.
export dbName=xyz
sqlcmd -Uusername -Sservername -Ppassword -i script.sql
:setvar dbName --remove this line
USE [$(dbName)]
GO
I think you're just not quoting the input variables correctly. I created this bash script...
#!/bin/bash
# Create a sql file with a parameterized test script
echo "
set nocount on
select k = '-db', v = '\$(db)' union all
select k = '-schema', v = '\$(schema)' union all
select '-', 'static'
go" > ./test.sql
# capture input variables
DB=$1
SCHEMA="${2:-dbo}"
# Exec sqlcmd
sqlcmd -S 'localhost\lemur' -E -i ./test.sql -v "db=${DB}" -v "schema=${SCHEMA}"
... and tested it like so:
$ ./test.sh master
k v
------- ------
-db master
-schema dbo
- static

Resources