网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > 数据库 > SQL技巧
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
数据库:数据库教程,数据库技巧,Oracle教程,MySQL教程,Sybase教程,Access教程,DB2教程,数据库安全,数据库文摘
本月文章推荐
.SAVEPOINT和ROLLBACK TO SAVEPOI.
.provider:命名管道提供程序error.
.在SQL Server中建立定时任务,处.
.SQL Server的链接服务器技术小结.
.解决sqlsever日志备份错误的方法 .
.数据库迁移的几种常用方式及优缺.
.SQL Server数据库sa密码相关问题.
.如何用dbms_rowid获取rowid的详细.
.Sql server安装2005中AdventureW.
.分布式查询和分布式事务.
.SQL Server数据库管理员必备的DB.
.教你使用SQL Server数据库进行网.
.用SQLServer2000索引视图提高性能.
.sql server转换时间为字符串.
.实现删除主表数据时, 判断与之关.
.标准SQL规范中定义的四个事务隔离.
.sql server 2000中的触发器使用.
.Microsoft SQL Server数据库SA权.
.查看当前进程,或死锁进程,并能自.
.32位到64位的sql server移植.

实现删除主表数据时, 判断与之关联的外键表是否有数据引用, 有标志, 无则删除

发表日期:2007-5-13


问题描述:
某个基础信息表,与系统中30多个表存在外键关系,当删除基础数据时,需要判断是否已经被用过,如果用过则更改标志位,如果没有用过则直接删除,如何能很好实现这个处理?最好能够自动适应表的变化
 
问题解决(SQL Server 2005)
-- SQL Server 2005的错误处理容易控制, 因此,SQL Server 2005中可以直接删除, 通过错误处理来确定是否需要更新.
 
-- 示例如下.
USE tempdb
GO
 
CREATE TABLE m(
    id int PRIMARY KEY,
    bz bit)
INSERT m SELECT 1, 0
UNION ALL SELECT 2, 0
 
CREATE TABLE c(
    id int primary key,
    a_id int references m(id)
        ON DELETE NO ACTION)
INSERT c SELECT 1, 1
GO
 
-- 删除处理存储过程
CREATE PROC dbo.p_delete
    @id int
AS
SET NOCOUNT ON
BEGIN TRY
BEGIN TRAN
    DELETE FROM m WHERE id = @id
COMMIT TRAN
END TRY
BEGIN CATCH
    ROLLBACK TRAN
    IF ERROR_NUMBER() = 547 -- 如果是外键约束错误
    BEGIN
        BEGIN TRY
        BEGIN TRAN          -- 更新标志
            UPDATE m SET bz = 1
            WHERE id = @id
        COMMIT TRAN
        END TRY
        BEGIN CATCH
            SELECT ERROR_NUMBER(), ERROR_MESSAGE()
        END CATCH
    END
    ELSE
        SELECT ERROR_NUMBER(), ERROR_MESSAGE()
END CATCH
GO
 
-- 调用
EXEC dbo.p_delete 1
EXEC dbo.p_delete 2
SELECT * FROM m
SELECT * FROM c
GO
 
DROP TABLE c, m
DROP PROC dbo.p_delete
 
问题解决(SQL Server 2000)
-- SQL Server 2000 对错误处理不好控制, 一般还是建议做判断
-- 通过系统表查询系统表,可以获取某个表关联的所有外键表
 
-- 示例存储过程
CREATE PROC dbo.p_Delete
    @tbname sysname,        -- 基础数据表名
    @PkFieldName sysname,   -- 基础数据表关键字段名
    @PkValue int            -- 要删除的基础数据表关键字值
AS
SET NOCOUNT ON
DECLARE @bz bit, @s nvarchar(4000)
DECLARE tb CURSOR LOCAL
FOR
SELECT N'
SET @bz = CASE WHEN EXISTS(
        SELECT * FROM ' + QUOTENAME(@tbname)
        + N' A, ' + QUOTENAME(OBJECT_NAME(B.fkeyid))
        + N' B
        WHERE A.' + QUOTENAME((SELECT name FROM syscolumns WHERE colid = B.rkey AND id = B.rkeyid))
        + N' = B.' + QUOTENAME((SELECT name FROM syscolumns WHERE colid = B.fkey AND id = B.fkeyid))
        + N' AND A.' + QUOTENAME((SELECT name FROM syscolumns WHERE colid = B.rkey AND id = B.rkeyid))
        + N' = @id) THEN 1 ELSE 0 END'
FROM sysobjects A
    JOIN sysforeignkeys B
        ON A.id= B.constid
    JOIN sysobjects C
        ON A.parent_obj = C.id
WHERE A.xtype = 'f'
    AND C.xtype = 'U'
    AND OBJECT_NAME(B.rkeyid) = @tbname
OPEN tb
FETCH tb INTO @s
WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC sp_executesql @s, N'@tbname sysname, @id int, @bz bit OUT', @tbname, @PkValue, @bz OUT
    IF @bz = 1
    BEGIN
        SET @s = N'UPDATE ' + QUOTENAME(@tbname)
            + N' SET bz = 1 WHERE ' + QUOTENAME(@PkFieldName)
            + N' = @id'
        EXEC sp_executesql @s, N'@id int', @PkValue
 
        RETURN
    END
 
    FETCH tb INTO @s
END
CLOSE tb
DEALLOCATE tb
 
SET @s = N'DELETE FROM ' + QUOTENAME(@tbname)
    + N' WHERE ' + QUOTENAME(@PkFieldName)
    + N' = @id'
EXEC sp_executesql @s, N'@id int', @PkValue
GO
 
注意事项
设置表的主/外键关系的时候,不要设置级联删除(ON DELETE CASCADE)
上一篇:SQL Server 2005 中能够使用 Try...Catch语句 人气:3159
下一篇:如何利用SQL查询返回庞大的整数序列表 人气:3022
浏览全部SQL server的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐