Gus*_*lfo 5 postgresql scripting dynamic-sql select
我正在尝试从旧表创建新表结构的更新,但不使用函数。我正在尝试为其创建一个脚本。旧表是这样的:
旧表 ( OldTable
)
姓名 | 可乐 | 列b | 列_c |
---|---|---|---|
ABC | 0 | 无效的 | 1 |
DEF | 1 | 1 | 1 |
生长激素指数 | 无效的 | 1 | 0 |
并且,新表:
Users
:
ID | 姓名 |
---|---|
1 | ABC |
2 | DEF |
3 | 生长激素指数 |
Rules
:
ID | 规则名称 |
---|---|
1 | 可乐 |
2 | 列b |
3 | 列_c |
4 | 寒冷的 |
UserRule
ID_USER | ID_规则 |
---|
因此,我需要使用 TableMix 上的选择结果填充表 UserRules,其中用户名等于表 User 上的用户名,并且 TableMix 中列 <col_name> 的值等于 1。(select <col_name>来自 OldTable,其中 OldTable.name = Users.name)。嗯,我正在尝试这个:
DO $$
DECLARE rules CURSOR FOR SELECT column_name FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'OldTable'
AND data_type = 'numeric' AND column_name NOT IN ('foo','bar');
-- "foo" and "bar" are another numeric cols, but not define rules.
DECLARE users CURSOR FOR SELECT name FROM public.Users;
BEGIN
FOR ruleName IN rules LOOP
FOR userName IN users LOOP
EXECUTE format('SELECT COALESCE(%I,col,$1) FROM public.OldTable
WHERE name = ''$2''', ruleName, username);
-- insert on... populate the table Rules after get the id of the rule in table Rules if the result of select in OldTable equals 1 (or true if has a "where ... = 1")
END LOOP;
END LOOP;
END $$
Run Code Online (Sandbox Code Playgroud)
在此之后,我没有任何进展。
更新
这样我就可以获得真正的价值:
DO $$
DECLARE
rules CURSOR FOR SELECT column_name FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'oldtable' AND data_type = 'numeric'
AND column_name NOT IN ('foo','bar');
names CURSOR FOR SELECT username FROM public.users;
res integer;
BEGIN
FOR rulename IN rules LOOP
EXECUTE format('SELECT %s FROM oldtable WHERE nome = %L', rulename, 'USER NAME') INTO res;
-- IF res > 0 THEN
RAISE NOTICE '%', res;
--END IF;
END LOOP;
END $$
Run Code Online (Sandbox Code Playgroud)
结果为实整数值。
但如果我对用户名使用循环,它就不起作用。
DO $$
DECLARE
rules CURSOR FOR SELECT column_name FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'oldtable' AND data_type = 'numeric'
AND column_name NOT IN ('foo','bar');
names CURSOR FOR SELECT username FROM public.users;
res integer;
BEGIN
FOR name IN names LOOP
FOR rulename IN rules LOOP
EXECUTE format('SELECT %s FROM oldtable WHERE nome = %L', rulename, name) INTO res;
-- IF res > 0 THEN
RAISE NOTICE '%', res;
--END IF;
END LOOP;
END LOOP;
END $$
Run Code Online (Sandbox Code Playgroud)
所以,结果总是 。我哪里错了?
我想您可能正在寻找以下USING
条款:
EXECUTE format('SELECT COALESCE(%I,col,$1) FROM public.TableMix
WHERE name = $2', ruleName)
USING (username, whateverTheSecondParameterIs);
Run Code Online (Sandbox Code Playgroud)
您使用$1
、$2
等作为放置参数,并通过 传递USING
。您使用%I
由 扩展的迭代器format
。
更新:如果你想合并列名(ruleName
如果它为空),也许你想要更多类似的东西:
EXECUTE format('SELECT %I FROM public.TableMix
WHERE name = $1', coalesce(ruleName, 'col'))
USING (username);
Run Code Online (Sandbox Code Playgroud)
??
您需要考虑评估顺序。生成的 SQL 的哪些部分以及为了创建该 SQL 而评估哪些内容?