我有一个 plpgsql 函数来使用 PostgreSQL 中的表继承创建子表,如下所示:
CREATE TABLE parent_table (
value integer,
end_time timestamp without time zone
);
CREATE OR REPLACE FUNCTION mk_child(_year INTEGER, _month INTEGER)
RETURNS text AS $$
DECLARE
tname varchar;
start_date date;
end_date date;
next_month varchar := (_month + 1)::text;
next_year varchar := (_year + 1)::text;
BEGIN
tname := 'child_y' || substring(_year::text from 3 for 2)
|| 'm' || lpad(_month::text, 2, '0');
start_date := DATE (_year::text || '-' || _month::text || '-01');
IF ( _month = 12 ) …Run Code Online (Sandbox Code Playgroud) 在设置使用随机 UUID 作为主键的数据库的脚本中,我有:
CREATE TABLE alpha (id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), value INT);
CREATE TABLE beta (aref UUID REFERENCES alpha (id));
INSERT INTO alpha (value) VALUES (42);
Run Code Online (Sandbox Code Playgroud)
然后通过外键,让“alpha”中的记录成为插入“beta”表的默认目标:
DO $$
DECLARE l_id UUID;
BEGIN
SELECT alpha.id FROM alpha INTO l_id;
ALTER TABLE beta ALTER COLUMN aref SET DEFAULT l_id;
END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)ERROR: column "l_id" does not exist CONTEXT: SQL statement "ALTER TABLE beta ALTER COLUMN aref SET DEFAULT l_id" PL/pgSQL function inline_code_block line 1 at SQL statement …
format我在使用下面示例中的函数正确引用表名时遇到一些问题。
CREATE OR REPLACE FUNCTION copy_table(_source_tbl regclass, _target_tbl text)
RETURNS bool AS $func$
DECLARE query_str text;
BEGIN
query_str = format($fmt$ DROP TABLE IF EXISTS %1$I; CREATE TABLE %1$I AS (TABLE %s); $fmt$, _target_tbl, _source_tbl);
EXECUTE query_str;
RAISE NOTICE '%', query_str;
RETURN True;
END $func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
我的困境是我想引用输入表名称_target_tbl作为标识符(以避免 SQL 注入)。但是,给定完整的表名称ex.test1,这会导致架构部分ex.被视为表名称的一部分,并public."ex.test1"在默认public.架构中创建表,如下所示。
我应该如何在此处正确引用/格式化标识符?
=> SELECT copy_table('ex.test', 'ex.test1');
NOTICE: table "ex.test1" does not exist, skipping
NOTICE: DROP TABLE IF EXISTS "ex.test1"; CREATE TABLE …Run Code Online (Sandbox Code Playgroud) 我想对ST_Intersection(clipper_geom, clipped_geom)来自表的行数执行。
https://postgis.net/docs/ST_Intersection.html
https://postgis.net/docs/ST_Intersects.html
POSTGIS 交集本身不支持处理多个几何图形,这与ST_Intersects()我必须设计一个函数(返回一个表)来选择与我的clipper_geomusing相交的行ST_Intersects()、循环遍历结果集并计算与 的每个交集有关ST_Intersection()。字段geom和clipped_geom_wkt是记录剪裁几何体的字段。
该功能有效,但我需要为每个要生成剪辑的表使用不同的功能。我想动态读取输入表(列名称和类型)并在RETURN语句中定义两者。
所有字段名称和类型都相同,只是geom更新和clipped_geom_wkt添加。
我尝试搜索 Stack Overflow,找到了有关如何创建动态表结构的示例,但没有一个LOOP对第一个结果执行后续操作,其中列名必须匹配才能插入/更新新数据。
这是我到目前为止所提出的,但我不确定如何执行该LOOP部分、添加clipped_geom_wkt字段和更新geom字段。一些回复建议RETURNS TABLE (...)如果添加更多字段SETOF...
但似乎动态生成的列仅支持RETURNS SETOF ...
CREATE OR REPLACE FUNCTION clip_palin_polygon_complete(clipped_table text,clipper_geom text, age_sequence VARCHAR)
RETURNS TABLE (rec clipped_table, clipped_geom_wkt text)) AS $$ --not sure if this is the right way to …Run Code Online (Sandbox Code Playgroud) 我遇到了一个奇怪的动态 sql 问题,我认为这是某种格式问题,在过去的几个小时里我一直在为此抓狂。我非常感谢我能得到的任何帮助。
对于一些背景信息,此存储过程的目的是清理我们的集中式 (hq) 数据库中的数据,该数据库应该拥有我们所有商店的所有记录的完整副本。如果重要的话,我们正在运行 Microsoft Dynamics RMS (2.0.2022) 和 SQL 2014 Standard(对于总部,商店使用 Express)。
最初我打算将 sql 语句放在参数中并使用 exec 命令,但是虽然我不经常使用它,但我认为 sp_executesql 看起来更干净,并且更容易将查询重用为模板并进行更改他们。现在我只有一些选择的脚本,但是一旦它们完成,我将创建一个额外的存储过程来插入、删除和更新记录。
执行 sql 语句有效,但出于某种原因,我无法让 sp_executesql 使用存储过程中的参数。无论我将参数更改为什么,包括在存储过程中使用静态值,它都只会输出参数名称。所以无论:
@LS = @LinkedServer
Run Code Online (Sandbox Code Playgroud)
或者
@LS = 'StaticLinkedServerName'
Run Code Online (Sandbox Code Playgroud)
它返回的错误信息是:
在 sys.servers 中找不到服务器“@LS”。验证是否指定了正确的服务器名称。如有必要,执行存储过程 sp_addlinkedserver 将服务器添加到 sys.servers。
无效的解决方案
CREATE PROCEDURE [dbo].[usp_bn_ShowStoreHQSync]
(
@StoreCode NVARCHAR(10)
,@LinkedServer NVARCHAR(50)
,@StoreDB NVARCHAR(40)
)
AS
BEGIN
BEGIN TRANSACTION
BEGIN TRY
IF @StoreCode IS NULL
RAISERROR('@StoreCode Cannot Be NULL',15,1)
ELSE IF @StoreCode NOT IN (SELECT StoreCode FROM [HQDB].[dbo].[Store])
RAISERROR('@StoreCode Not In DB',15,1) …Run Code Online (Sandbox Code Playgroud) 假设我有两个经常针对我的数据库运行的查询:
SELECT
UserID,
UserName,
UserGender
FROM Users
WHERE UserID = @User
SELECT
UserID,
UserName,
UserGender
FROM Users
WHERE UserName LIKE @Name + '%
Run Code Online (Sandbox Code Playgroud)
它们应该在两个单独的存储过程中,还是只是一个使用 sp_executesql 动态创建语句的存储过程?
如果它们在两个存储过程中,那么如果我想在 SELECT 语句中添加或删除列,我将需要修改这两个过程。如果我使用动态 SQL,那么大概我会牺牲少量的性能。
在这种情况下,使用动态 SQL 的可维护性和遵守 DRY 原则(不要重复自己)会优先于存储过程的性能增益吗?
对于一份报告,我正在查询用户假设必须根据百分比选择 TOP 值或固定行数。
我有两个想法
根据传递的参数调用两个不同的子存储过程。
if @param ='percent'
begin
exec sp_data_TOP_by_Percent
end
if @param ='perRow'
begin
exec sp_data_TOP_by_PerRow
end
Run Code Online (Sandbox Code Playgroud)
另一个想法是使动态 TSQL 查询像这样
declare @command nchar(max)
select @command = 'select top(10) '
+ case @param
when 'percent' then percent
else ' '
end
+ ' * '
+ 'from table
order by 1';
exec sp_executesql @command
Run Code Online (Sandbox Code Playgroud)
像这样的事情有第三种解决方案吗?
什么是更好的方法?第一个避免动态 TSQL,但在两个地方更难维护代码。我使用 MSSQL2005 作为数据库。
我的表是这样的:
Sitecode Month Amount
-------- ----- ------
XX Jan 1000
XX Jan 3000
XX Apr 3000
XX Apr 1000
Run Code Online (Sandbox Code Playgroud)
我想要的是,显示这样的结果:
Sitecode MonthJAN MonthAPR
-------- -------- --------
XX 4000 4000
Run Code Online (Sandbox Code Playgroud) 我已经用 Postgres 玩了一个星期左右,我正在看看是否可以使用表达式设置序列的最小值/最大值。具体目标是为服务器之间的不相交范围自动创建脚本,以避免多主设置中的密钥冲突。
例如,使用 psql:
CREATE SEQUENCE key_seq MINVALUE (:servernum * :stride)
MAXVALUE ((:servernum + 1) * :stride - 1);
Run Code Online (Sandbox Code Playgroud)
这给了我一个语法错误。变量是逐字内插的,不进行计算。
另一种方法是根据表达式的输出设置变量:
\set minvalue (:servernum * :stride)
Run Code Online (Sandbox Code Playgroud)
但该\set语句不计算表达式。
我发现exec(sql)代码中隐藏了一些语句。它们存在是有充分理由的,因为这些语句不能直接编写,但它们是一个明显的攻击媒介。
有没有安全的替代品exec(some sql)?将正确参数化的东西,包括语句中的表名?
dynamic-sql ×10
postgresql ×5
plpgsql ×4
sql-server ×4
t-sql ×3
ddl ×2
alter-table ×1
parameter ×1
pivot ×1
postgis ×1
psql ×1
security ×1
sequence ×1