我设计了一个大型的sql脚本,因此它是安全的。在不同实例上运行,或在同一实例上多次运行而不会导致任何错误数据或错误
编写这样的脚本时,我总是依赖于语法:
from datetime import datetime
from datetime import timedelta
movies = [
"13:00 Alien Beetroot",
"15:30 Bananas Go Bad!",
"17:45 Cheerleader Lake",
"19:00 Yoghurt Spoon Eater",
"21:10 Zombie A Go-Go",
"23:30 Shark Snacks VI",
"02:15 Drive-In Dinosaur Disaster"
]
myTime = "18:30"
myDate = "Wed 03 November 2015"
cineDate = "Wed 03 November 2015"
t = datetime.strptime(myDate + " " + myTime, "%a %d %B %Y %H:%M")
for i in range(0, len(movies)):
sp = movies[i].split(" ", 1)
tim = sp[0]
mov = sp[1]
show = datetime.strptime(cineDate + " " + tim, "%a %d %B %Y %H:%M")
if show.time() >= t.time():
print tim + " " + mov
这通常效果很好。但是,我最近遇到了一种情况,我无法阻止在执行期间抛出错误。在下面的代码中,列" deprecated_column"已经从表Foo中删除了:
if not exists (select 1 from SYS.FOREIGN_KEYS where NAME = 'FK_BAR')
begin
alter table [MyTable]
add constraint FK_BAR foreign key (some_id) references Other_Table(some_id)
end
go
如果我独立于此计划在if exists (select 1 from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'Foo' and COLUMN_NAME = 'deprecated_column')
and exists (select 1 from [Foo] where new_column is null)
begin
declare @updated int set @updated = 1;
while @updated > 0
begin
update top (500000)
Foo
set new_column = deprecated_column
where new_column is null
;
set @updated = @@rowcount;
end
end
go
内运行两个exist
,则会返回"没有结果"正如所料,这意味着永远不会执行内部代码。但是,当我运行脚本时,服务器会抛出错误:if
,并且脚本被标记为带有错误的完成,这会导致在我们的系统上引发警报(即,DBA会收到通知并且必须check),这会导致一些简单的自动化任务产生一些不必要的开销。
是否有一些我忽略的语法允许此代码在所有情况下都能正常运行?
答案 0 :(得分:2)
正如我在评论中解释的那样,T-SQL是一种编译语言,“无效列”是编译器错误,而不是执行错误。但是,由于大多数T-SQL只是在执行之前编译,所以当你经常看到它时。
由于T-SQL尝试编译所有代码而不管IF分支,因此唯一的解决方法就是使用动态SQL。像这样:
if exists (select 1 from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'Foo' and COLUMN_NAME = 'deprecated_column')
and exists (select 1 from [Foo] where new_column is null)
begin
EXEC('
declare @updated int set @updated = 1;
while @updated > 0
begin
update top (500000)
Foo
set new_column = deprecated_column
where new_column is null
;
set @updated = @@rowcount;
end
');
end
go