In the first query, your variables are identifiers, whereas in the second they're literal strings.
You shouldn't be putting parenthesis with the identifiers, and they shouldn't be wrapped in single quotes unless you further wrap them with double quotes.
For instance, this would create a table called 'foo'
rather than foo
:
create table "'foo'" ();
And these would all spit out errors:
create table 'foo' (); -- requires double quotes
create table (foo) (); -- unexpected parenthesis
create table ('foo') (); -- both problems
If you really want to use parameters for identifiers, you'll need to use a dynamic SQL statement. In this case, you'll also need to worry about quoting the identifiers using PG if applicable, e.g.:
DO $$
BEGIN
PERFORM ' CREATE TABLE ' || quote_ident(%s) || ' ()';
END;
$$;
In the above, the outer string is delimited by $$
, and the inner strings are delimited by '
. After parameters get replaced, it'll look like:
' CREATE TABLE ' || quote_ident('foo') || ' ()'
And then:
' CREATE DATABASE ' || '"foo"' || ' ()'
And finally:
' CREATE DATABASE "foo" ()'
This particular statement of yours, however, cannot be part of a transaction so cannot go in a do statement. As such, you'll need to resort to doing the string manipulation in Python directly.
What quote_ident()
does is, in essence, wrap in double quotes after doubling all double quotes in the input. For instance:
# select quote_ident('foo"bar');
quote_ident
-------------
"foo""bar"
(1 row)
I'm not familiar enough with Python to write that for you, but that's basically the subroutine you'll need to make it work. Then pass the final SQL string — with the parameters in it replaced — to Postgres directly.