Using positional parameter ($1,..) in psql

给你一囗甜甜゛ 提交于 2019-12-23 09:04:06

问题


I often want to copy/paste sql out of my program code and test/debug in psql and it is tedious to have to replace positional arguments with literal values. Is there a good way to convert:

select * from users where name=$1 and email=$2; 

to:

select * from users where name='troy' and email='t@me.com';

回答1:


You could use psql variables. Those are interpolated in SQL code. Per documentation:

A key feature of psql variables is that you can substitute ("interpolate") them into regular SQL statements, as well as the arguments of meta-commands. Furthermore, psql provides facilities for ensuring that variable values used as SQL literals and identifiers are properly quoted. The syntax for interpolating a value without any quoting is to prepend the variable name with a colon (:).

Note that (per documentation):

The name must consist of letters (including non-Latin letters), digits, and underscores.

So you cannot work with positional parameters of the form $1. I am assuming you copy these pieces of code from function bodies, and that's the reason for the positional parameters?
Since PostgreSQL 9.2, even SQL functions can reference parameters by name. Per documentation:

Arguments of a SQL function can be referenced in the function body using either names or numbers.

PL/pgSQL functions have been supporting named parameters in the function body since v8.0.

My preferred naming convention is to prepend function parameters with _ to avoid naming conflicts. But that's a matter of taste and style.

Only half a solution

So, your example could work like this:

db=> \set _name 'troy'
db=> \set _email 't@me.com'
db=> select * from users where name=:'_name' and email=:'_email'; 

You still have to prepare query strings ...
Note the quotes in :'_name'. That has the same effect as applying quote_literal() on the string. Details in the manual.




回答2:


It's not a whole lot better than just running the original query, but assuming that your example is only a trivial one and the actual query is a bit more involved, you could create a function:

CREATE OR REPLACE FUNCTION get_users(user_name varchar, email_addr varchar)
  RETURNS SETOF users AS
$BODY$
  select *
  from users
  where
    name = user_name and
    name = email_addr
$BODY$
  LANGUAGE sql VOLATILE
  COST 100
  ROWS 1000;

To get the results you would:

select * from get_users('troy', 't@me.com')

Again with your example, this doesn't help a whole lot, but I've used this with big queries with lots of joins, and it works nicely.



来源:https://stackoverflow.com/questions/25090153/using-positional-parameter-1-in-psql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!