函数中的 Postgres 语法错误
Postgres syntax error in a function
我正在尝试创建一个函数,但在以下代码中找不到我的错误:
CREATE OR REPLACE FUNCTION qwat_od.fn_label_create_fields(table_name varchar, position boolean = true, rotation boolean = true) RETURNS void AS
$BODY$
BEGIN
/* Creates columns */
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_visible smallint default 1; ';
IF position IS TRUE THEN
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_x double precision default null;';
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_y double precision default null;';
END IF;
IF rotation IS TRUE THEN
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_rotation double precision default null;';
END IF;
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_text varchar(120);';
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_visible smallint default 1; ';
IF position IS TRUE THEN
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_x double precision default null;';
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_y double precision default null;';
END IF;
IF rotation IS TRUE THEN
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_rotation double precision default null;';
END IF;
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_text varchar(120);';
/* Creates constraints */
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD CONSTRAINT '||table_name||'_label_1_visible FOREIGN KEY (label_1_visible) REFERENCES qwat_vl.visible(vl_code_int) MATCH FULL; CREATE INDEX fki_'||table_name||'_label_1_visible ON qwat_od.'||table_name||'(label_1_visible);';
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD CONSTRAINT '||table_name||'_label_2_visible FOREIGN KEY (label_2_visible) REFERENCES qwat_vl.visible(vl_code_int) MATCH FULL; CREATE INDEX fki_'||table_name||'_label_2_visible ON qwat_od.'||table_name||'(label_2_visible);';
END;
$BODY$
LANGUAGE 'plpgsql';
我明白了:
ERROR: syntax error at or near "position"
LINE 4: ...wat_od.fn_label_create_fields(table_name varchar, position b...
我是不是在参数声明中做错了什么?
因为您看到的错误。
但还有更多。最重要的是,您对 SQL injection 持开放态度。
CREATE OR REPLACE FUNCTION qwat_od.fn_label_create_fields(_tbl text, _position bool = true, _rotation bool = true)
RETURNS void AS
$func$
BEGIN
/* Creates columns */
EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_1_visible smallint default 1', _tbl);
IF _position THEN
EXECUTE format('ALTER TABLE qwat_od.%I
ADD COLUMN label_1_x double precision default null
, ADD COLUMN label_1_y double precision default null', _tbl);
END IF;
IF _rotation THEN
EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_1_rotation double precision default null' , _tbl);
END IF;
EXECUTE format('ALTER TABLE qwat_od.%I
ADD COLUMN label_1_text varchar(120)
, ADD COLUMN label_2_visible smallint default 1', _tbl);
IF _position THEN
EXECUTE format('ALTER TABLE qwat_od.%I
ADD COLUMN label_2_x double precision default null
, ADD COLUMN label_2_y double precision default null', _tbl);
END IF;
IF _rotation THEN
EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_2_rotation double precision default null', _tbl);
END IF;
EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_2_text varchar(120)', _tbl);
/* Creates constraints */
EXECUTE format('ALTER TABLE qwat_od.%I
ADD CONSTRAINT %I FOREIGN KEY (label_1_visible) REFERENCES qwat_vl.visible(vl_code_int)
, ADD CONSTRAINT %I FOREIGN KEY (label_2_visible) REFERENCES qwat_vl.visible(vl_code_int);
CREATE INDEX %I ON qwat_od.%I(label_1_visible);
CREATE INDEX %I ON qwat_od.%I(label_2_visible)'
, _tbl
, _tbl || '_label_1_visible'
, _tbl || '_label_2_visible'
, 'fki_' || _tbl || '_label_1_visible'
, 'fki_' || _tbl || '_label_2_visible');
END
$func$ LANGUAGE plpgsql;
一定要使用明确、有效的参数名称(position
是 reserved word 是主要错误)。
我用 format()
修复了你的 SQL 注入问题(因为 regclass
的简单解决方案没有涵盖你的串联名称,正如@pozs 所评论的).详细解释:
- INSERT with dynamic table name in trigger function
- Table name as a PostgreSQL function parameter
_tbl
必须是不合格的 table 名称("tbl"
,而不是 "schema.tbl"
)。
不要引用语言名称,它是一个标识符:LANGUAGE plpgsql
在单个 ALTER TABLE
语句中添加多个列/子约束更便宜。
其他各种简化/优化。
我正在尝试创建一个函数,但在以下代码中找不到我的错误:
CREATE OR REPLACE FUNCTION qwat_od.fn_label_create_fields(table_name varchar, position boolean = true, rotation boolean = true) RETURNS void AS
$BODY$
BEGIN
/* Creates columns */
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_visible smallint default 1; ';
IF position IS TRUE THEN
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_x double precision default null;';
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_y double precision default null;';
END IF;
IF rotation IS TRUE THEN
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_rotation double precision default null;';
END IF;
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_1_text varchar(120);';
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_visible smallint default 1; ';
IF position IS TRUE THEN
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_x double precision default null;';
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_y double precision default null;';
END IF;
IF rotation IS TRUE THEN
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_rotation double precision default null;';
END IF;
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD COLUMN label_2_text varchar(120);';
/* Creates constraints */
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD CONSTRAINT '||table_name||'_label_1_visible FOREIGN KEY (label_1_visible) REFERENCES qwat_vl.visible(vl_code_int) MATCH FULL; CREATE INDEX fki_'||table_name||'_label_1_visible ON qwat_od.'||table_name||'(label_1_visible);';
EXECUTE 'ALTER TABLE qwat_od.'||table_name||' ADD CONSTRAINT '||table_name||'_label_2_visible FOREIGN KEY (label_2_visible) REFERENCES qwat_vl.visible(vl_code_int) MATCH FULL; CREATE INDEX fki_'||table_name||'_label_2_visible ON qwat_od.'||table_name||'(label_2_visible);';
END;
$BODY$
LANGUAGE 'plpgsql';
我明白了:
ERROR: syntax error at or near "position"
LINE 4: ...wat_od.fn_label_create_fields(table_name varchar, position b...
我是不是在参数声明中做错了什么?
但还有更多。最重要的是,您对 SQL injection 持开放态度。
CREATE OR REPLACE FUNCTION qwat_od.fn_label_create_fields(_tbl text, _position bool = true, _rotation bool = true)
RETURNS void AS
$func$
BEGIN
/* Creates columns */
EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_1_visible smallint default 1', _tbl);
IF _position THEN
EXECUTE format('ALTER TABLE qwat_od.%I
ADD COLUMN label_1_x double precision default null
, ADD COLUMN label_1_y double precision default null', _tbl);
END IF;
IF _rotation THEN
EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_1_rotation double precision default null' , _tbl);
END IF;
EXECUTE format('ALTER TABLE qwat_od.%I
ADD COLUMN label_1_text varchar(120)
, ADD COLUMN label_2_visible smallint default 1', _tbl);
IF _position THEN
EXECUTE format('ALTER TABLE qwat_od.%I
ADD COLUMN label_2_x double precision default null
, ADD COLUMN label_2_y double precision default null', _tbl);
END IF;
IF _rotation THEN
EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_2_rotation double precision default null', _tbl);
END IF;
EXECUTE format('ALTER TABLE qwat_od.%I ADD COLUMN label_2_text varchar(120)', _tbl);
/* Creates constraints */
EXECUTE format('ALTER TABLE qwat_od.%I
ADD CONSTRAINT %I FOREIGN KEY (label_1_visible) REFERENCES qwat_vl.visible(vl_code_int)
, ADD CONSTRAINT %I FOREIGN KEY (label_2_visible) REFERENCES qwat_vl.visible(vl_code_int);
CREATE INDEX %I ON qwat_od.%I(label_1_visible);
CREATE INDEX %I ON qwat_od.%I(label_2_visible)'
, _tbl
, _tbl || '_label_1_visible'
, _tbl || '_label_2_visible'
, 'fki_' || _tbl || '_label_1_visible'
, 'fki_' || _tbl || '_label_2_visible');
END
$func$ LANGUAGE plpgsql;
一定要使用明确、有效的参数名称(
position
是 reserved word 是主要错误)。我用
format()
修复了你的 SQL 注入问题(因为regclass
的简单解决方案没有涵盖你的串联名称,正如@pozs 所评论的).详细解释:- INSERT with dynamic table name in trigger function
- Table name as a PostgreSQL function parameter
_tbl
必须是不合格的 table 名称("tbl"
,而不是"schema.tbl"
)。不要引用语言名称,它是一个标识符:
LANGUAGE plpgsql
在单个
ALTER TABLE
语句中添加多个列/子约束更便宜。其他各种简化/优化。