Oracle如何在将一个数据库中的所有表都加上某些字段。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle如何在将一个数据库中的所有表都加上某些字段。相关的知识,希望对你有一定的参考价值。
1.如何查出数据库中所有表中不包含MODIFIER字段的表,
select distinct
TABLE_NAME from user_tab_columns a
where a.COLUMN_NAME <> 'MODIFIER' 得到的值为什么不正确。
2.我如何将得到的一组表同时加上MODIFIER NVARCHAR2(120)字段,即用得到的表结果集来替换下列语句中的表名。
declare
vstr_sql varchar2(2000):='alter table 表名 add MODIFIER NVARCHAR2(120) not null)';
begin
execute immediate vstr_sql;
end;
希望各位指教,3Q.
需要用存储过程解决。
如数据库中存在两张表,要给两张表都增加两个同样名称同样属性的字段,需要用以下代码:
1、创建测试用表test和test1
create table test(id int,
name varchar2(10));
create table test1
(id int,
name varchar2(10));
2、要为两个表同时增加id1和name1字段。使用代码:
declarev_sql varchar2(2000);
v_table_name varchar2(30);
cursor c1 is select table_name from user_tables;
begin
open c1;
loop --提取一行数据到c1
fetch c1 into v_table_name;
--判读是否提取到值,没取到值就退出
--取到值c_job%notfound 是false
--取不到值c_job%notfound 是true
exit when c1%notfound;
v_sql:=\'alter table \'||v_table_name||\' add id1 int\';
execute immediate v_sql;
v_sql:=\'alter table \'||v_table_name||\' add name1 varchar2(10)\';
execute immediate v_sql;
end loop;--关闭游标
close c1;
end;
如图:
3、执行代码,成功无误后,查询test表和test1表结构:
select distinct a.TABLE_NAME from user_tab_columns a where a.TABLE_NAME not in (SELECT b.TABLE_NAME from user_tab_columns b where b.COLUMN_NAME=‘MODIFIER’);
仔细想想你就明白为什么你写的不对了,希望能够解答你的疑惑。
提示:你并没有把包含指定列的表的情况除去追问
我没弄清楚user_tab_columns视图包含的字段意义,谢谢了!现在理清楚了。
追答嗯,思路很重要
参考技术B declarevstr_sql varchar2(2000);
cursor c1 is select distinct a.TABLE_NAME TABLE_NAME from user_tab_columns a
where a.TABLE_NAME not in (SELECT b.TABLE_NAME from user_tab_columns b where b.COLUMN_NAME=‘MODIFIER’);
begin
for rec in c1 loop
vstr_sql varchar2(2000):='alter table '||rec.TABLE_NAME||' add MODIFIER NVARCHAR2(120) not null)';
execute immediate vstr_sql;
end loop;
end;本回答被提问者采纳
如果所有表都不存在,请添加一列?
【中文标题】如果所有表都不存在,请添加一列?【英文标题】:Add a column if it doesn't exist to all tables? 【发布时间】:2011-07-05 23:42:45 【问题描述】:我使用的是 SQL Server 2005/2008。如果表尚不存在,我需要向表中添加一列。这将适用于给定数据库中的所有表。我希望我很接近,但我遇到了这个解决方案的问题。
如何做到这一点?
这是我所拥有的:
EXEC sp_MSforeachtable '
declare @tblname varchar(255);
SET @tblname = PARSENAME("?",1);
if not exists (select column_name from INFORMATION_SCHEMA.columns
where table_name = @tblname and column_name = ''CreatedOn'')
begin
ALTER TABLE @tblname ADD CreatedOn datetime NOT NULL DEFAULT getdate();
end
'
但我得到错误:
错误 102:“@tblname”附近的语法不正确。 “CreatedOn”附近的语法不正确。 '@tblname' 附近的语法不正确。 “CreatedOn”附近的语法不正确。 ... 等等,对于每个表。
【问题讨论】:
***.com/questions/1779743/… 的可能重复项 @JAiro:这绝对是一个相关的链接,但是“如果不存在”规则很重要,并且让它变得更复杂一些。 好的,你可以用这个来完成信息:***.com/questions/133031/… 您问题的根本原因是依赖于 INFORMATION_SCHEMA 视图并且必须将名称拆分为模式和对象。只需使用object_id(''?'')
就可以了。更快的检查是if COLUMNPROPERTY(object_id(''?''), ''CreatedOn'', ''ColumnId'') is null
。
【参考方案1】:
您不能在 DDL 中使用变量,例如 @tableName。此外,将名称分成部分并忽略模式只会导致错误。您应该只在 SQL 批处理参数中使用 ''?'' 替换并依赖 MSforeachtable
替换:
EXEC sp_MSforeachtable '
if not exists (select * from sys.columns
where object_id = object_id(''?'')
and name = ''CreatedOn'')
begin
ALTER TABLE ? ADD CreatedOn datetime NOT NULL DEFAULT getdate();
end';
【讨论】:
请记住,sp_msforeachtable 是不受支持的存储过程,因此不应将其用于生产代码。尽管它添加了几行代码,但如果您使用定义为从 sys.schemas 和 sys.tables 中选择的 游标,则您使用的是 T-SQL 的文档化部分,您可以选择只改变一个WHERE表达式就可以影响全部或部分表,性能是一样的。此外,如果您使用 quotename 函数,您可以处理更少的名称限定符。最后,您可以更灵活地使用您希望的架构/表名称(即用于日志)。 @PhilHelmer 这连同一个例子会是一个很好的答案。【参考方案2】:您需要混合一些动态 SQL。这应该有效:
EXEC sp_MSforeachtable '
declare @tblname varchar(255);
SET @tblname = PARSENAME("?",1);
declare @sql nvarchar(1000);
if not exists (select column_name from INFORMATION_SCHEMA.columns
where table_name = @tblname and column_name = ''CreatedOn'')
begin
set @sql = N''ALTER TABLE '' + @tblname + N'' ADD CreatedOn datetime NOT NULL DEFAULT getdate();''
exec sp_executesql @sql
end
'
【讨论】:
@Remus:是的,如果 OP 正在使用模式,那么这将成为一个问题。为您的回答 +1。【参考方案3】:DECLARE @Column VARCHAR(100) = 'Inserted_date'
DECLARE @sql VARCHAR(max) = NULL
SELECT @sql += ' ALTER TABLE ' + QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) + 'ADD' + @Column + 'datetime NOT NULL DEFAULT getdate()' + '; '
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME IN (
SELECT DISTINCT NAME
FROM SYS.TABLES
WHERE type = 'U'
AND Object_id IN (
SELECT DISTINCT Object_id
FROM SYS.COLUMNS
WHERE NAME != @Column
)
)
EXEC Sp_executesql @sql
【讨论】:
考虑为您的答案添加解释。也许也删除代码的屏幕截图...... 嗨,Jean,实际上我只是将列名存储在一个变量中,并找出该特定列不存在的表名,然后将 alter 命令保存在另一个变量 @sql 中我们运行执行添加。【参考方案4】:可能是这样的:
EXEC sp_MSforeachtable '
declare @tblname varchar(255);
SET @tblname = PARSENAME("?",1);
if not exists (select column_name from INFORMATION_SCHEMA.columns
where table_name = @tblname and column_name = ''CreatedOn'')
begin
ALTER TABLE [?] ADD CreatedOn datetime NOT NULL DEFAULT getdate();
end
'
?
甚至像这样:
EXEC sp_MSforeachtable '
if not exists (select column_name from INFORMATION_SCHEMA.columns
where table_name = ''?'' and column_name = ''CreatedOn'')
begin
ALTER TABLE [?] ADD CreatedOn datetime NOT NULL DEFAULT getdate();
end
'
【讨论】:
-1 在发布之前显然没有对此进行测试。[?]
在已经用括号括起来的名称周围添加括号,导致 [[schemaname].[tablename]]
这是不正确的。
@Remus Rusanu:我对此进行了测试:sp_MSforeachtable 'EXEC sp_help ?; EXEC sp_columns ?'
。这给出了语法错误。然后我把它改成sp_MSforeachtable 'EXEC sp_help [?]; EXEC sp_columns [?]'
,它工作了(SQL Server 2008 R2)。
...但是您没有测试 OP ALTER TABLE [?]
。 sp_help
和 sp_columns
都是存储过程,?
替换不起作用,因为 sp_help [foo].[bar]
是无效语法。但是sp_help [[foo]].[bar]]]
是正确的语法,并且由于参数的处理方式,它实际上最终可以工作。 ALTER TABLE [[foo]].[bar]]]
虽然不起作用。长话短说:您发布的代码没有通过基本的语法检查,任何人都可以验证。
@Remus Rusanu:我不是在争论。我发布我的测试示例有两个原因:提供我错觉的原因,并可能有人解释我为什么会被错觉(除了我无知的明显原因)。所以,最后,谢谢。 :)
哦,对不起,我误解了你的 cmets。 sp_help [?]
的工作方式至少对我来说也很神秘。以上是关于Oracle如何在将一个数据库中的所有表都加上某些字段。的主要内容,如果未能解决你的问题,请参考以下文章
如何查询一个oracle数据库中所有表的所有字段哪个包含特定字符串?