从本质上讲,我想做的是:
所以说我有类似
的东西SELECT COLUMN_NAME, TABLE_NAME, TABLE_SCHEMA
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
(
TABLE_SCHEMA = 'PUBLIC'
) AND (
COLUMN_NAME LIKE '%SOMETHING%'
OR COLUMN_NAME LIKE '%SOMETHINGELSE%'
) AND (
DATA_TYPE = 'BIGINT' OR
DATA_TYPE = 'TINYINT' OR
DATA_TYPE = 'SMALLINT' OR
DATA_TYPE = 'INTEGER'
)
或者对于Oracle来说:
SELECT COLUMN_NAME, TABLE_NAME
FROM USER_TAB_COLS
WHERE
(
COLUMN_NAME LIKE '%SOMETHING%'
OR COLUMN_NAME LIKE '%SOMETHINGELSE%'
) AND
DATA_TYPE IN ('NUMBER')
我想在所有结果列上执行UPDATE
,类似于:
UPDATE _RESULTING_COLUMN_NAMES_HERE_THEORETICALLY_
SET
_SINGLE_COLUMN_NAME_ = _SOME_NEW_VALUE_
WHERE _SINGLE_COLUMN_NAME_ = _SOME_OLD_VALUE_;
很明显,这不起作用甚至不存在,但我希望你明白我想要达到的目标。
我可以看到为UPDATE
结果集中的每个匹配表生成SELECT
语句的方法,但我真的没有看到如何实现这一点。
为了让事情变得更有趣,我需要为old_value到new_value转换列表这样做。
欢迎任何想法。
我正在尝试将HSQLDB和Oracle作为我的2项要求,但支持其他平台将是一个相当不错的奖励。
答案 0 :(得分:1)
只要您认为需要使用动态SQL,就应该停下来,退后一步,看看是否有其他方法可以做到这一点,或者您是否真的需要做什么你在做什么。
我可能会严重质疑你的基础"要求"的:
有些东西仍然闻起来有趣"有趣" ...我非常小心你正在做什么 - 确保你知道结果会是什么,测试测试...再次测试......在某个DEV盒子上...
说,无论何时我需要求助于动态SQL,我发现最简单的方法是从"模板"开始:
所以在你的情况下,你想要触发的最终更新是你所说的:
UPDATE _RESULTING_COLUMN_NAMES_HERE_THEORETICALLY_
SET
_SINGLE_COLUMN_NAME_ = _SOME_NEW_VALUE_
WHERE _SINGLE_COLUMN_NAME_ = _SOME_OLD_VALUE_;
好的,我现在可能会将其重新编写为字符串,并使用WITH子句启动查询:
WITH w_template AS ( select
rtrim(q'[ UPDATE _RESULTING_COLUMN_NAMES_HERE_THEORETICALLY_ ]')||CHR(10)||
rtrim(q'[ SET ]')||CHR(10)||
rtrim(q'[ _SINGLE_COLUMN_NAME_ = _SOME_NEW_VALUE_ ]')||CHR(10)||
rtrim(q'[ WHERE _SINGLE_COLUMN_NAME_ = _SOME_OLD_VALUE_; ]')
template from dual
)
注意我还没有改变你的查询中的任何内容。我所做的只是将"q'["
和"]'"
包围起来...... rtrim
,CHR(10)
并将其放在WITH
子句中。
1)q'[ some string ]'
是另一种做字符串的方法。它的优点是你可以在该字符串中使用单引号而没有任何实际问题:
即q'[ some 'string' ]'
工作得很好......打印" some 'string' "
2)RTRIM
- 我在那里留下了作为装饰品的行尾的空格,以便我们更容易阅读。但是,由于字符串的长度限制,这些空间可以增长,字符串非常大,非常快,查询量更大。所以RTRIM
是我养成的习惯。保留化妆品空间,但告诉Oracle不要使用它们;)它们只适合我们。
3)CHR(10)
- 仅限化妆品 - 如果您愿意,可以将其关闭。我喜欢它,就像你想在测试期间转储查询一样,你可以轻松阅读查询并查看它的内容。
接下来我们将更改动态值的名称,以便我们更轻松地发现它们并替换它们:
WITH w_template AS ( select
rtrim(q'[ UPDATE <table_name> ]')||CHR(10)||
rtrim(q'[ SET ]')||CHR(10)||
rtrim(q'[ <col_name> = <col_new_val> ]')||CHR(10)||
rtrim(q'[ WHERE <col_name> = <col_old_val>; ]')
template from dual
)
我所做的就是创建一个易于识别的&#34;字符串&#34;我将在以后用它替换值。
注意如果您的列是字符串,则可能需要引号:<col_name> = '<col_new_val>'
但似乎你正在处理整数数据..所以我认为我们还好......
现在我们需要提取您的数据......所以我们回到您的原始查询:
SELECT COLUMN_NAME, TABLE_NAME
FROM USER_TAB_COLS
WHERE
(
COLUMN_NAME LIKE '%SOMETHING%'
OR COLUMN_NAME LIKE '%SOMETHINGELSE%'
) AND
DATA_TYPE IN ('NUMBER')
嗯,我在那里的查询中必须相信你,我不确定它会在Oracle上运行,但你比我更了解你的查询;)所以我&#39 ; ll相信你的查询&#34;原样&#34;对于这个例子 - 只要它选择你想要的数据,并包括你想要的表名,列名和前/后值(它目前没有),我们就可以了。< / p>
所以我们需要做的就是将这两者结合起来......我们会这样做:
WITH w_template AS ( select
rtrim(q'[ UPDATE <table_name> ]')||CHR(10)||
rtrim(q'[ SET ]')||CHR(10)||
rtrim(q'[ <col_name> = <col_new_val> ]')||CHR(10)||
rtrim(q'[ WHERE <col_name> = <col_old_val>; ]')
template from dual
)
w_data AS (
SELECT COLUMN_NAME, TABLE_NAME
FROM USER_TAB_COLS
WHERE
(
COLUMN_NAME LIKE '%SOMETHING%'
OR COLUMN_NAME LIKE '%SOMETHINGELSE%'
) AND
DATA_TYPE IN ('NUMBER')
)
然后我们只需添加最终查询,使用REPLACE替换值..
(注意:不知道你得到了什么&#34; some_new_value&#34;以及&#34; some_old_value&#34;来自???你必须将它加入你的查询..)
WITH w_template AS ( select
rtrim(q'[ UPDATE <table_name> ]')||CHR(10)||
rtrim(q'[ SET ]')||CHR(10)||
rtrim(q'[ <col_name> = <col_new_val> ]')||CHR(10)||
rtrim(q'[ WHERE <col_name> = <col_old_val>; ]')
template from dual
),
w_data AS (
SELECT COLUMN_NAME, TABLE_NAME
FROM USER_TAB_COLS
WHERE
(
COLUMN_NAME LIKE '%SOMETHING%'
OR COLUMN_NAME LIKE '%SOMETHINGELSE%'
) AND
DATA_TYPE IN ('NUMBER')
)
SELECT REPLACE ( REPLACE ( REPLACE ( REPLACE (
wt.template, '<table_name>',
wd.table_name ),
'<col_name>', wd.column_name ),
'<col_new_val>', ??? ),
'<col_old_val>', ??? ) query
FROM w_template wt,
w_data wd
我离开了?那里有旧的/新的价值观,因为你没有说明他们来自哪里?
但如果你运行它,应该吐出一些更新语句..;)
一旦你对这些感到满意,推动他们立即执行是一件容易的事。
同样,我建议对这种方法保持谨慎,这对于1次迁移是可以的,或者这样,但是,不建议每天定期运行。 ;)
答案 1 :(得分:0)
查找与特定查询匹配的所有表及其列, 更新这些列中的值。
使用HSQLDB时,不可能仅使用SQL来执行此操作。您需要编写一个简短的Java程序来列出所需的表名及其列名,然后为每个表构造一个UPDATE语句并执行它。
使用Oracle,您可以在PL / SQL中编写相同的程序。但Java语言解决方案与两个数据库引擎兼容。