Thread: variable substitution in SQL commands

variable substitution in SQL commands

From
bill house
Date:
Hello,

I am trying to learn how to construct SQL commands using information
derived from other SQL commands/querys.

These commands are stored for the moment in a simple text file which
would be executed by the psql client like so:

    current_database=# \i sql_command_file.sql

In this file I want to store a path name to a data directory in a
variable and then concatenate that path with a file name (of a csv file)
to then copy said file into a table.

I have not been able to discover a straightforward way to do this so as
a work-around, I created a table and stored the information there to use
later.

It works, but

    1) Is there a better way to do this?

Now that that works,

    2) I would like to take the results of a query extracting/constructing
the desired data (path/file) and inserting that data into another SQL
command like so:

    COPY test_table FROM (SELECT constructed path/file) WITH CSV;

My research has indicated that there may be several approaches and I
have tried several that I thought I understood, but I don't have command
of all the nuances of constructing SQL statements.

The following is a file containing my commands with various trials and
results.

Any guidance would be appreciated.

Thanks,

Bill

=================================================

-----set path for cvs data
--see http://www.pgadmin.org/docs/dev/pgscript.html
--declare @data_path character varying (40);
--set @data_path = '/home/some_user/test_data';
--Nope! use a table

--create a schema or name space
CREATE SCHEMA testing;
--comment out if it already exists

DROP TABLE testing.mem_var;
CREATE TABLE testing.mem_var
  (
         mem_name                character varying (40) PRIMARY KEY,
         mem_content             character varying (1024)

);

--add my path variable
INSERT INTO testing.mem_var VALUES (
   'data_path',
   '/home/some_user/test_data'
);


--create the tables

--############################# test_table ############################
/*
--Commented out for the present
DROP TABLE testing.test_table;
CREATE TABLE testing.test_table
  (
         field_01                        character varying (10),
         field_02                        character varying (6),
         field_03                        character varying (12)

);
*/

--Doesn't work: SELECT mem_content FROM testing.mem_var
--    WHERE mem_name = 'data_path';
--Doesn't work: SELECT mem_content FROM testing.mem_var
--    WHERE mem_name = 'data_path' ||


/*This works!

SELECT mem_content || '/test_table.csv' AS cvs_file FROM
testing.mem_var     WHERE mem_name = 'data_path';

returns:
                                     cvs_file
------------------------------------------------------------------------------
/home/some_user/test_data/test_table.csv
(1 row)

--Put parenthesis around my value to return to make it clearer what I am
doing.
--Still works.

SELECT (mem_content || '/test_table.csv') AS cvs_file FROM
testing.mem_var WHERE mem_nam = 'data_path';

Now to substitute the above query (or it's results) into an SQL command
COPY etc., etc.,
*/


-- Does not work.
COPY testing.test_table
    FROM (SELECT mem_content || '/test_table.csv'
    AS cvs_file
    FROM testing.mem_var
    WHERE mem_name = 'data_path')
    WITH CSV;

/*
Hmmmm. Could use mem_var table here too i.e.
   retrieve path
   construct path/file string and store
   retrieve path_file
   construct whole statement and store
   retrieve statement and execute
   Maybe as a last resort if I don't figure this out.
   See also 8.3 manual pages 575~6 Dynamic SQL
                       pages 600~1 Using SQL Descriptor Areas
   psql client
      see man page %`command`
      \set

   OK, I give up. Use the mem_var table
*/

/*
Nope!
INSERT INTO testing.mem_var VALUES (
   'path_file',
   SELECT (mem_content || '/test_table.csv')
    AS cvs_file
    FROM testing.mem_var
    WHERE mem_name = 'data_path'
);
*/

/*
Nope!
INSERT INTO testing.mem_var VALUES (
   'path_file',
   SELECT (mem_content || '/test_table.csv')
    FROM testing.mem_var
    WHERE mem_name = 'data_path'
);
*/

/*
Nope!
SELECT (mem_content || '/test_table.csv')
    AS cvs_file
    FROM testing.mem_var
    WHERE mem_nam = 'data_path';
INSERT INTO testing.mem_var VALUES (
   'path_file',
   cvs_file
);
*/


/*
Nope!, at least not in this form
--from http://www.faqs.org/docs/ppbook/x5504.htm
-- Practical Postgresql Ch 4 Adding Data with INSERT and COPY
INSERT INTO testing.mem_var (mem_name, mem_content)
   'path_file',
   SELECT (mem_content || '/test_table.csv')
    AS cvs_file
    FROM testing.mem_var
    WHERE mem_name = 'data_path'

--Maybe insert the record, then update it with the value
*/


INSERT INTO testing.mem_var VALUES (
   'path_file',
   ''
)


--BEGIN/COMMIT? Man page 18

UPDATE testing.mem_var
   SET mem_content =
    SELECT (mem_content || '/test_table.csv')
    AS cvs_file
    FROM testing.mem_var
    WHERE mem_name = 'data_path')
    WHERE mem_name - 'path_file);






Re: variable substitution in SQL commands

From
Tom Lane
Date:
bill house <wchouse@bellsouth.net> writes:
> I am trying to learn how to construct SQL commands using information
> derived from other SQL commands/querys.
> These commands are stored for the moment in a simple text file which
> would be executed by the psql client like so:
>     current_database=# \i sql_command_file.sql

This is really getting beyond what you can do usefully with a simple
psql text file.  My first suggestion would be to see if you can write
what you need as a plpgsql function.

            regards, tom lane

Re: variable substitution in SQL commands

From
bill house
Date:
Tom Lane wrote:
> bill house <wchouse@bellsouth.net> writes:
>> I am trying to learn how to construct SQL commands using information
>> derived from other SQL commands/querys.
>> These commands are stored for the moment in a simple text file which
>> would be executed by the psql client like so:
>>     current_database=# \i sql_command_file.sql
>
> This is really getting beyond what you can do usefully with a simple
> psql text file.  My first suggestion would be to see if you can write
> what you need as a plpgsql function.
>
>             regards, tom lane
>

I was afraid you were going to say that.  This was the indication that I
was getting from my reading, but I just wanted to make sure this trip
was really necessary.

Thanks,

Bill House

Re: variable substitution in SQL commands

From
bill house
Date:
bill house wrote:
> Tom Lane wrote:
>> bill house <wchouse@bellsouth.net> writes:
>>> I am trying to learn how to construct SQL commands using information
>>> derived from other SQL commands/querys.
>>> These commands are stored for the moment in a simple text file which
>>> would be executed by the psql client like so:
>>>     current_database=# \i sql_command_file.sql
>>
>> This is really getting beyond what you can do usefully with a simple
>> psql text file.  My first suggestion would be to see if you can write
>> what you need as a plpgsql function.
>>
>>             regards, tom lane
>>
>
> I was afraid you were going to say that.  This was the indication that I
> was getting from my reading, but I just wanted to make sure this trip
> was really necessary.
>
> Thanks,
>
> Bill House
>
This is a followup on this subject with my findings re: memory variables
from a close reading of the psql man page.

Also a demonstration of my accidental discovery of the (undocumented?)
ability to chain scripts.

This ability has obvious positive implications.

Thanks

Bill


--######################## zz_test_variable_01.sql ############
-- test of memory variables and echo output in psql
-- based on reading of psql man page

-- also demonstrates file chaining

--set test_var_1
\set test_var_1 'this is test_var_1'

--set test_var_2
\set test_var_2 'this is test_var_2'

--give me a new line
\echo

--echo test_var_1
\echo :test_var_1

--echo test_var_2
\echo :test_var_2

--echo test_var_1 plus attempt to concatenate something
\echo :test_var_1'another string'
--output: this is test_var_1 another string
--                          ^note space, get rid of it

\echo :test_var_1:test_var_2
--output: this is test_var_1 this is test_var_2
--                          ^note space, get rid of it
\set test_var_3 ':test_var1another string'
\echo :test_var_3
--output: :test_var1another string

\set test_var_4 :test_var_1 '/another string'
\echo :test_var_4
--output: this is test_var_1/another string
--Now that's what I'm talking about
--I should be able to construct paths and file names

--call another script
\i zz_test_variable_01a.sql
---------------------end of zz_test_variable_01.sql

--############### zz_test_variable_01a.sql ############################
-- demonstrates file chaining and availability of memory variables
-- called from zz_test_variable_01.sql

\echo
\echo 'This script is zz_test_variable_01a.sql.'
\echo 'It demonstrates the ability of psql to chain files, one calling
another'
\echo 'with the \i meta command.'
\echo 'It was called by the script zz_test_varible_01.sql'
\echo 'This script can also access memory variables set by the calling
file.'
\echo 'In this case, test_var_4.
\echo :test_var_4
\echo
-----------------------end of zz_test_variable_01a.sql

All of the above yields:
=================================================
world=# \i zz_test_variable_01.sql

this is test_var_1
this is test_var_2
this is test_var_1 another string
this is test_var_1 this is test_var_2
:test_var1another string
this is test_var_1/another string

This script is zz_test_variable_01a.sql.
It demonstrates the ability of psql to chain files, one calling another
with the i meta command.
It was called by the script zz_test_varible_01.sql
This script can also access memory variables set by the calling file.
psql:zz_test_variable_01a.sql:11: unterminated quoted string

this is test_var_1/another string

world=#
=================================================