How do I use session variables in Netezza nzsql?

2019-06-13 12:57发布

  1. How do I create and use session variables in Netezza nzsql?

  2. How can I use session variables as part of strings?

    • Can I concatenate session variables with strings?
    • Can I embed session variables in strings?
  3. How can I use them as part of table names or column names?

标签: netezza nzsql
1条回答
聊天终结者
2楼-- · 2019-06-13 13:51

Basic Variable Usage

The documentation for session variables in Netezza nzsql is somewhat lacking.
It states that in order to set a variable within a script or at the nzsql prompt, you use \set.

\set var value

You can also specify the variable at the command line. This is useful for passing variables into scripts.

nzsql -v var=value

Within your session or script, you can access the value of that variable as :var

DB.TST(LLAMA)=> \set foo example_table

DB.TST(LLAMA)=> \d :foo
                       Table "EXAMPLE_TABLE"
   Attribute    |         Type          | Modifier | Default Value
----------------+-----------------------+----------+---------------
 EXAMPLE_COLUMN | CHARACTER VARYING(16) |          |
Distributed on hash: "EXAMPLE_COLUMN"

DB.TST(LLAMA)=> SELECT * FROM :foo;
 EXAMPLE_COLUMN
----------------
 Hello World

Advanced Variable Usage

The \set command also has undocumented capabilities that add greater flexibility.
In reality, \set takes all values passed to it and concatenates them together.

DB.TST(LLAMA)=> \set foo bar baz qux
DB.TST(LLAMA)=> \echo :foo
barbazqux

The command also supports quoting in a manner similar to shell scripts which allows you to include whitespace within your variables.
Be careful though, quoted and unquoted strings will still be concatenated with each other.

DB.TST(LLAMA)=> \set foo 'bar baz qux'
DB.TST(LLAMA)=> \echo :foo
bar baz qux

DB.TST(LLAMA)=> \set foo 'bar baz' qux
DB.TST(LLAMA)=> \echo :foo
bar bazqux

Double quoting also works to preserves whitespace. However, the double quotes will still be preserved in the variable.

DB.TST(LLAMA)=> \set foo "bar baz qux"
DB.TST(LLAMA)=> \echo :foo
"bar baz qux"

DB.TST(LLAMA)=> \set foo "bar baz" qux
DB.TST(LLAMA)=> \echo :foo
"bar baz"qux

Of course, the different types of quoting can be mixed:

DB.TST(LLAMA)=> \set foo "Hello World" 'Goodbye World'
DB.TST(LLAMA)=> \echo :foo
"Hello World"Goodbye World

Single Quotes

Properly embedding single quotes in a \set command can be difficult.
Incidentally, because double quotes are always preserved, they rarely present a problem.

Single quotes within an unquoted word will be preserved.

DB.TST(LLAMA)=> \set foo bar'baz'qux
DB.TST(LLAMA)=> \echo :foo
bar'baz'qux

Single quotes within a quoted word may result in issues.

DB.TST(LLAMA)=> \set foo 'bar'baz'qux'
DB.TST(LLAMA)=> \echo :foo
barbaz'qux'

Single quotes within a doubly quoted value are preserved.

DB.TST(LLAMA)=> \set foo "This'll work fine!"
DB.TST(LLAMA)=> \echo :foo
"This'll work fine!"

Single quotes on their own need to be quoted and escaped.

DB.TST(LLAMA)=> \set foo '
parse error at end of line

DB.TST(LLAMA)=> \set foo \'
Invalid command \'. Try \? for help.

DB.TST(LLAMA)=> \set foo '\''
DB.TST(LLAMA)=> \echo :foo
'

When in doubt: single quote the phrase and escape all remaining single quotes with backslashes.

DB.TST(LLAMA)=> \set foo '\'bar\'baz\'qux\''
DB.TST(LLAMA)=> \echo :foo
'bar'baz'qux'

Variables In Identifiers

Occasionally you will need to use a variable as part of an identifier (i.e. a column or table name).
Consider the following example table and variable:

DB.TST(LLAMA)=> SELECT * FROM example_table;
 BAR_COLUMN  | QUX_COLUMN
-------------+-------------
 This is bar | This is qux
(1 row)

DB.TST(LLAMA)=> \set foo bar

In this example, you want to select bar_column using your variable :foo (which contains bar) and the text _column.
The following will not work:

DB.TST(LLAMA)=> SELECT :foo_column FROM example_table;
foo_column:
ERROR:  'SELECT  FROM example_table;'
error            ^ found "FROM" (at char 9) expecting an identifier found a keyword

The above example fails because nzsql cannot determine where the variable name ends (:foo) and the remaining column (_column) name begins.
To fix this, you need to make a new variable with \set by concatenating the value of :foo and the rest of the column name:

DB.TST(LLAMA)=> \set fixed_foo :foo _column
DB.TST(LLAMA)=> \echo :fixed_foo
bar_column

DB.TST(LLAMA)=> SELECT :fixed_foo FROM example_table;
 BAR_COLUMN
-------------
 This is bar
(1 row)

If the variable contains the end of the identifier you wish to use, no intermediate variables need to be created.
In that specific case, nzsql will properly expand the variable (e.g. column_:foo -> column_bar).


Stringification

Sometimes you will need to use the contents of a variable as a string.
Consider the following example table and variable:

DB.TST(LLAMA)=> SELECT * FROM example_table;
 EXAMPLE_COLUMN
----------------
 Hello World
 Whatever
 Something
(3 rows)

DB.TST(LLAMA)=> \set foo Something

If you simply quote the variable within the statement then it will be treated as literal text.

DB.TST(LLAMA)=> SELECT * FROM example_table WHERE example_column = 'Something';
 EXAMPLE_COLUMN
----------------
 Something
(1 row)

DB.TST(LLAMA)=> SELECT * FROM example_table WHERE example_column = ':foo';
 EXAMPLE_COLUMN
----------------
(0 rows)

DB.TST(LLAMA)=> \p
SELECT * FROM example_table WHERE example_column = ':foo';

If you leave the variable unquoted then it will be used as an identifier.

DB.TST(LLAMA)=> SELECT * FROM example_table WHERE example_column = :foo;
ERROR:  Attribute 'SOMETHING' not found

To fix this, you need to use \set and your knowledge of quoting to create a usable variable.
You can accomplish this by making a new variable by combining a single quote (properly escaped!), the variable's contents, and another single quote.

DB.TST(LLAMA)=> \set quoted_foo '\'' :foo '\''
DB.TST(LLAMA)=> \echo :quoted_foo
'Something'

DB.TST(LLAMA)=> SELECT * FROM example_table WHERE example_column = :quoted_foo;
 EXAMPLE_COLUMN
----------------
 Something
(1 row)

If your variable needs to be used inside of a string, it may be easier to stringify your variable and use regular string concatenation.

DB.TST(LLAMA)=> SELECT * FROM example_table WHERE example_column LIKE '%ello%';
 EXAMPLE_COLUMN
----------------
 Hello World
(1 row)

DB.TST(LLAMA)=> \set foo ello
DB.TST(LLAMA)=> \set quoted_foo '\'' :foo '\''
DB.TST(LLAMA)=> \echo :quoted_foo
'ello'

DB.TST(LLAMA)=> SELECT * FROM example_table WHERE example_column LIKE '%' || :quoted_foo || '%';
 EXAMPLE_COLUMN
----------------
 Hello World
(1 row)
查看更多
登录 后发表回答