邹建sql
1. 邹建的作者简介
中国着名企业家邹建,江西景德镇人士,闲逛网创始人。
邹建,熟悉数据库技术,对MS sql Server数据库体系结构、备份恢复、设计、管理、性能优化等都有深入研究,项目经验丰富,擅长数据库优化及故障诊断,现任职于某电子商务公司,资深DBA,负责数据库管理与维护工作。
2. 初学者学习SQL用那本书比较好
《深入浅出——SQL Server 2000开发、管理与应用实例》
作者:邹健
编着出版社:人民邮电出版社
出版时间:2008年08月
定价:59元
本书从应用、开发和管理3个角度逐步深入,全面介绍SQL Server 2000数据库技术,不但整合了资深专家数年工作实践和宝贵经验,还根据DBA所需具备的从业素质规划了内容结构。
本书全面系统地介绍了SQL Server开发和管理的应用技术,涉及安装和配置SQL Server、日期处理、字符处理、排序规则、编号处理、数据统计与汇总、分页处理、树形数据处理、数据导入与导出、作业、数据备份与还原、用户定义数据类型、数据库安全、系统表应用实例、索引、事务及锁、SQL Server应用疑难解答等内容。
本书不但融合了作者在使用SQL Server 2000过程中遇到的各种常见问题和应用案例,还总结了作者几年来在CSDN社区SQL Server版所解决的大量问题,面向实际项目需求,涉及不同类型的应用,能够多角度地引导读者学习相关知识。针对各类问题,书中提供了详细的操作步骤和解决思路,具有很强的实用性和可操作性。
本书适用于已经掌握了SQL Server基础知识,但缺少实践经验的读者,对初学者来说更是一本入门与进阶的必备指导用书。
邹建,网名ZJCXC,CSDN社区MS SQL Server版大版主,微软2004—2007 SQL Server MVP(微软最有价值专家)。着有《中文版SQL Server 2000开发与管理应用实例》一书,该书深受读者好评。熟悉数据库技术,对MS SQL Server数据库体系结构、备份恢复、设计、管理、性能优化等都有深
3. 在SQL数据库中附加数据库时遇到如下错误,请问如何解决执行 Transact-SQL 语句或批处理时发生了异常
转csdn
sql专家邹建的解决办法
作者:邹建
直接restore或附加应该是不行的,
用脚本+导数据肯定没有问题。
2005转到2000的步骤步骤
1.
生成for
2000版本的数据库脚本
2005
的manger
studio
--
打开"对象资源管理器"(没有的话按F8),
连接到你的实例
--
右键要转到2000的库
--
任务
--
生成脚本
--
在"脚本向导"的"选择数据库"中,
确定选择的是要转到2000的库
--
勾选"为所选数据库中的所有对象编写脚本"
--
在接下来的"选择脚本选项"中,
找到"为服务器版本编写脚本"项,
选择"SQL
Server
2000"
--
其他选项根据需要设置
--
最后把脚本保存到一个
.sql
脚本文件
2.
在2000中创建目标数据库
在查询分析器(或2005的manger
studio在打开脚本文件),
连接到SQL
Server
2000,执行上面生成的脚本.以创建一个新的数据库
3.
将数据从2005导到2000
2005
的manger
studio
--
打开"对象资源管理器"(没有的话按F8),
连接到你的实例
--
右键要转到2000的库
--
任务
--
导出数据
--
在"SQL
Server
导入和导出向导"的"选择数据源"步骤中,
确定选择的是要导出的数据库
--
在"选择目标"步骤中,
连接到
2000,
并选择步骤2新建的库
--
在"选择源表和源视图"中,
选择所有的表
--
最后完成
4. 邹建的介绍
邹建,CSDN社区MS SQL Server版大版主,微软2004-2007 SQL Server MVP(微软最有价值专家)。着有《中文版SQL Server 2000开发与管理应用实例》一书,该书深受读者好评。
5. SQL比较两张表的异同
*--比较两个数据库的表结构差异
--邹建 2003.9(引用请保留此信息)--*/
/*--调用示例
exec p_comparestructure 'xzkh_model','xzkh_new'
--*/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_comparestructure]') and OBJECTPROPERTY(id, N'IsProcere') = 1)
drop procere [dbo].[p_comparestructure]
GO
create proc p_comparestructure
@dbname1 varchar(250), --要比较的数据库名1
@dbname2 varchar(250) --要比较的数据库名2
as
create table #tb1(表名1 varchar(250),字段名 varchar(250),序号 int,标识 bit,主键 bit,类型 varchar(250),
占用字节数 int,长度 int,小数位数 int,允许空 bit,默认值 varchar(500),字段说明 varchar(500))
create table #tb2(表名2 varchar(250),字段名 varchar(250),序号 int,标识 bit,主键 bit,类型 varchar(250),
占用字节数 int,长度 int,小数位数 int,允许空 bit,默认值 varchar(500),字段说明 varchar(500))
--得到数据库1的结构
exec('insert into #tb1 SELECT
表名=d.name,字段名=a.name,序号=a.colid,
标识=case when a.status=0x80 then 1 else 0 end,
主键=case when exists(SELECT 1 FROM '+@dbname1+'..sysobjects where xtype=''PK'' and name in (
SELECT name FROM '+@dbname1+'..sysindexes WHERE indid in(
SELECT indid FROM '+@dbname1+'..sysindexkeys WHERE id = a.id AND colid=a.colid
))) then 1 else 0 end,
类型=b.name, 占用字节数=a.length,长度=a.prec,小数位数=a.scale, 允许空=a.isnullable,
默认值=isnull(e.text,''''''),字段说明=isnull(g.[value],'''''')
FROM '+@dbname1+'..syscolumns a
left join '+@dbname1+'..systypes b on a.xtype=b.xusertype
inner join '+@dbname1+'..sysobjects d on a.id=d.id and d.xtype=''U'' and d.name<>''dtproperties''
left join '+@dbname1+'..syscomments e on a.cdefault=e.id
left join '+@dbname1+'..sysproperties g on a.id=g.id and a.colid=g.smallid
order by a.id,a.colorder')
--得到数据库2的结构
exec('insert into #tb2 SELECT
表名=d.name,字段名=a.name,序号=a.colid,
标识=case when a.status=0x80 then 1 else 0 end,
主键=case when exists(SELECT 1 FROM '+@dbname2+'..sysobjects where xtype=''PK'' and name in (
SELECT name FROM '+@dbname2+'..sysindexes WHERE indid in(
SELECT indid FROM '+@dbname2+'..sysindexkeys WHERE id = a.id AND colid=a.colid
))) then 1 else 0 end,
类型=b.name, 占用字节数=a.length,长度=a.prec,小数位数=a.scale, 允许空=a.isnullable,
默认值=isnull(e.text,''''''),字段说明=isnull(g.[value],'''''')
FROM '+@dbname2+'..syscolumns a
left join '+@dbname2+'..systypes b on a.xtype=b.xusertype
inner join '+@dbname2+'..sysobjects d on a.id=d.id and d.xtype=''U'' and d.name<>''dtproperties''
left join '+@dbname2+'..syscomments e on a.cdefault=e.id
left join '+@dbname2+'..sysproperties g on a.id=g.id and a.colid=g.smallid
order by a.id,a.colorder')
--and not exists(select 1 from #tb2 where 表名2=a.表名1)
select 比较结果=case when a.表名1 is null and b.序号=1 then '库1缺少表:'+b.表名2
when b.表名2 is null and a.序号=1 then '库2缺少表:'+a.表名1
when a.字段名 is null and exists(select 1 from #tb1 where 表名1=b.表名2) then '库1 ['+b.表名2+'] 缺少字段:'+b.字段名
when b.字段名 is null and exists(select 1 from #tb2 where 表名2=a.表名1) then '库2 ['+a.表名1+'] 缺少字段:'+a.字段名
when a.标识<>b.标识 then '标识不同'
when a.主键<>b.主键 then '主键设置不同'
when a.类型<>b.类型 then '字段类型不同'
when a.占用字节数<>b.占用字节数 then '占用字节数'
when a.长度<>b.长度 then '长度不同'
when a.小数位数<>b.小数位数 then '小数位数不同'
when a.允许空<>b.允许空 then '是否允许空不同'
when a.默认值<>b.默认值 then '默认值不同'
when a.字段说明<>b.字段说明 then '字段说明不同'
else '' end,
*
from #tb1 a
full join #tb2 b on a.表名1=b.表名2 and a.字段名=b.字段名
where a.表名1 is null or a.字段名 is null or b.表名2 is null or b.字段名 is null
or a.标识<>b.标识 or a.主键<>b.主键 or a.类型<>b.类型
or a.占用字节数<>b.占用字节数 or a.长度<>b.长度 or a.小数位数<>b.小数位数
or a.允许空<>b.允许空 or a.默认值<>b.默认值 or a.字段说明<>b.字段说明
order by isnull(a.表名1,b.表名2),isnull(a.序号,b.序号)--isnull(a.字段名,b.字段名)
go
6. 创建安全帐户的sql语句有哪些
创建角色,用户,权限 /*--示例说明 示例在数据库pubs中创建一个拥有表jobs的所有权限、拥有表titles的SELECT权限的角色r_test 随后创建了一个登录l_test,然后在数据库pubs中为登录l_test创建了用户账户u_test 同时将用户账户u_test添加到角色r_test中,使其通过权限继承获取了与角色r_test一样的权限 最后使用DENY语句拒绝了用户账户u_test对表titles的SELECT权限。 经过这样的处理,使用l_test登录SQL Server实例后,它只具有表jobs的所有权限。 --*/ USE pubs --创建角色 r_test EXEC sp_addrole 'r_test' --授予 r_test 对 jobs 表的所有权限 GRANT ALL ON jobs TO r_test --授予角色 r_test 对 titles 表的 SELECT 权限 GRANT SELECT ON titles TO r_test --添加登录 l_test,设置密码为pwd,默认数据库为pubs EXEC sp_addlogin 'l_test','pwd','pubs' --为登录 l_test 在数据库 pubs 中添加安全账户 u_test EXEC sp_grantdbaccess 'l_test','u_test' --添加 u_test 为角色 r_test 的成员 EXEC sp_addrolemember 'r_test','u_test' --拒绝安全账户 u_test 对 titles 表的 SELECT 权限 DENY SELECT ON titles TO u_test /*--完成上述步骤后,用 l_test 登录,可以对jobs表进行所有操作,但无法对titles表查询,虽然角色 r_test 有titles表的select权限,但已经在安全账户中明确拒绝了对titles的select权限,所以l_test无titles表的select权限--*/ --从数据库 pubs 中删除安全账户 EXEC sp_revokedbaccess 'u_test' --删除登录 l_test EXEC sp_droplogin 'l_test' --删除角色 r_test EXEC sp_droprole 'r_test' SQL code --1. 创建示例环境。首先使用下面的代码创建一个登录l_test,并且为登录在数据库pubs中创建关联的用户账户u_test,并且授予用户账户u_test对表titles的SELECT权限,用以实现登录l_test连接到SQL Server实例后,可以访问表titles。然后创建了一个应用程序角色r_p_test,授予该角色对表jobs的SELECT权限,用以实现激活r_p_test时,允许访问特定的表jobs。USE pubs--创建一个登录 l_test, 密码 pwd, 默认数据库 pubsEXEC sp_addlogin 'l_test','pwd','pubs' --为登录 l_test 在数据库 pubs 中添加安全账户 u_testEXEC sp_grantdbaccess 'l_test','u_test'--授予安全账户 u_test 对 titles 表的 SELECT 权限GRANT SELECT ON titles TO u_test--创建一个应用程序角色 r_p_test, 密码 abcEXEC sp_addapprole 'r_p_test','abc'--授予角色 r_p_test 对 jobs 表的 SELECT 权限GRANT SELECT ON jobs TO r_p_testGO--2. 激活应用程序角色。/*--激活说明 示例环境创建完成后,在任何地方(比如查询分析器、应用程序) 使用登录l_test连接SQL Server实例,均只能访问表titles,或者是guest用户 和public角色允许访问的对象。 如果要在某些特定的应用程序中,允许登录访问表jobs,那么, 可以激活应用程序角色r_p_test,激活应用程序角色后,登录本身的权限会消失。 下面在查询分析器中登录,演示激活应用程序角色r_p_test前后对数据访问的区别。--*/--激活应用程序角色 r_p_test 前,登录具有表 titles 的访问权,但无表 jobs 的访问权SELECT titles_count=COUNT(*) FROM titlesSELECT jobs_count=COUNT(*) FROM jobs/*--结果:titles_count ------------ 18(所影响的行数为 1 行)服务器: 消息 229,级别 14,状态 5,行 2拒绝了对对象 'jobs'(数据库 'pubs',所有者 'dbo')的 SELECT 权限。--*/GO--用密码 abc 激活 r_p_test 应用程序角色,并且在将此密码发送到SQL Server之前对其加密EXEC sp_setapprole 'r_p_test',{Encrypt N'abc'},'ODBC'GO--激活应用程序角色 r_p_test 后,登录失去表 titles 的访问权,获取表 jobs 的访问权SELECT titles_count=COUNT(*) FROM titlesSELECT jobs_count=COUNT(*) FROM jobs/*--结果服务器: 消息 229,级别 14,状态 5,行 2拒绝了对对象 'titles'(数据库 'pubs',所有者 'dbo')的 SELECT 权限。jobs_count ----------- 14(所影响的行数为 1 行)--*/ SQL code exec sp_dropsrvrolemember N'aa', sysadmingoexec sp_addsrvrolemember N'aa', securityadmingo--作好SQL的安全管理--作者:邹建首先,做好用户安全: --简单的,只允许sql的用户访问sql(防止利用administrator组用户访问) 1.企业管理器--右键SQL实例--属性--安全性--身份验证--选择"sql server和windows"--确定 2.企业管理器--安全性--登陆--右键sa--设置密码--其他用户也设置密码 3.删除用户: BUILTIN\Administrators <机器名>\Administrator --这个用户不一定有 这样可以防止用windows身份登陆SQL 4.设置进入企业管理器需要输入密码 在企业管理器中 --右键你的服务器实例(就是那个有绿色图标的) --编辑SQL Server注册属性 --选择"使用 SQL Server 身份验证" --并勾选"总是提示输入登录名和密码" --确定 --经过上面的设置,你的SQL Server基本上算是安全了. ------------------------------------------------------------------------ 其次,改默认端口,隐藏服务器,减少被攻击的可能性 SQL Server服务器 --开始 --程序 --Microsoft SQL Server --服务器网络实用工具 --启用的协议中"TCP/IP" --属性 --默认端口,输入一个自已定义的端口,比如2433 --勾选隐藏服务器 ---------------------------------------------------------------------------- --管好sql的用户,防止访问他不该访问的数据库(总控制,明细还可以控制他对于某个数据库的具体对象具有的权限) --切换到你新增的用户要控制的数据库 use 你的库名 go --新增用户 exec sp_addlogin 'test' --添加登录 exec sp_grantdbaccess N'test' --使其成为当前数据库的合法用户 exec sp_addrolemember N'db_owner', N'test' --授予对自己数据库的所有权限 --这样创建的用户就只能访问自己的数据库,及数据库中包含了guest用户的公共表 go --删除测试用户 exec sp_revokedbaccess N'test' --移除对数据库的访问权限 exec sp_droplogin N'test' --删除登录 如果在企业管理器中创建的话,就用:企业管理器--安全性--右键登录--新建登录常规项--名称中输入用户名--身份验证方式根据你的需要选择(如果是使用windows身份验证,则要先在操作系统的用户中新建用户)--默认设置中,选择你新建的用户要访问的数据库名服务器角色项这个里面不要选择任何东西数据库访问项勾选你创建的用户需要访问的数据库名数据库角色中允许,勾选"public","db_ownew"确定,这样建好的用户与上面语句建立的用户一样 --------------------------------------------------------------------------- 最后一步,为具体的用户设置具体的访问权限,这个可以参考下面的最简示例: --添加只允许访问指定表的用户: exec sp_addlogin '用户名','密码','默认数据库名' --添加到数据库 exec sp_grantdbaccess '用户名' --分配整表权限 GRANT SELECT , INSERT , UPDATE , DELETE ON table1 TO [用户名]--分配权限到具体的列GRANT SELECT , UPDATE ON table1(id,AA) TO [用户名] ------------------------------------------------------------------- 至于具体的安全设置和理论知道,参考SQL联机帮助 SQL code /*--创建一个只允许特定程序使用的数据库用户 创建一个用户,这个用户只有用我们特定的应用程序登录 才具有访问数据库的权限,用其他工具登录没有任何权限 在下面的示例中,演示了如何控制登录l_test 使其登录后只允许访问pubs数据库的titles表 而对jobs表的访问权限,只允许在某些许可的应用程序中访问。--邹建 2004.09(引用请保留此信息)--*/--创建测试环境USE pubs--创建一个登录 l_test, 密码 pwd, 默认数据库 pubsEXEC sp_addlogin 'l_test','pwd','pubs' --为登录 l_test 在数据库 pubs 中添加安全帐户 u_testEXEC sp_grantdbaccess 'l_test','u_test'--授予安全帐户 u_test 对 titles 表的 SELECT 权限GRANT SELECT ON titles TO u_test--创建一个应用程序角色 r_p_test, 密码 abcEXEC sp_addapprole 'r_p_test','abc'--授予角色 r_p_test 对 jobs 表的 SELECT 权限GRANT SELECT ON jobs TO r_p_testGO--创建好上面的测试后,现在来测试如何使用应用程序角色--我们把用户及密码告诉使用者,即告诉使用者,用户是: l_test,密码是: pwd--使用者可以用我们这个用户在任何地方登录,包含查询分析器--但是,用户只能访问 titles 表,不能访问其他对象,如果建立用户时不授予它任何权限,则它不访问除guest用户和public角色允许访问外的任何对象--OK,到这里,我们是把用户控制住了--下面我们再来说在程序中的处理,因为用户在程序中登录后,需要对jobs表有访问权限的--我们只需要在用户登录后,执行一句 EXEC sp_setapprole 'r_p_test',{Encrypt N'abc'},'ODBC'--这样,我们登录的用户就转变为 r_p_test 角色的权限,而它自身的权限丢失--只要这个用户不退出应用程序,他的权限就会保持--如果用户退出了当前应用程序,则他的权限自动收回--同时,这个用户即使没有退出应用程序,他也是只在我们的应用程序中有权限,在其他地方登录,也不会有权限--因为这个密码我们是不用给用户的,所以,用户没有这个角色的密码,也就限制了他只能在程序中使用我们的数据--激活应用程序角色 r_p_test 前,登录具有表 titles 的访问权,但无表 jobs 的访问权SELECT titles_count=COUNT(*) FROM titlesSELECT jobs_count=COUNT(*) FROM jobs/*--结果:titles_count ------------ 18(所影响的行数为 1 行)服务器: 消息 229,级别 14,状态 5,行 2拒绝了对对象 'jobs'(数据库 'pubs',所有者 'dbo')的 SELECT 权限。--*/GO--用密码 abc 激活 r_p_test 应用程序角色,并且在将此密码发送到SQL Server之前对其加密EXEC sp_setapprole 'r_p_test',{Encrypt N'abc'},'ODBC'GO--激活应用程序角色 r_p_test 后,登录失去表 titles 的访问权,获取表 jobs 的访问权SELECT titles_count=COUNT(*) FROM titlesSELECT jobs_count=COUNT(*) FROM jobs/*--结果服务器: 消息 229,级别 14,状态 5,行 2拒绝了对对象 'titles'(数据库 'pubs',所有者 'dbo')的 SELECT 权限。jobs_count ----------- 14(所影响的行数为 1 行)--*/go--删除测试EXEC sp_dropapprole 'r_p_test'EXEC sp_revokedbaccess 'u_test'EXEC sp_droplogin 'l_test'
7. SQL2005 附加 2008 数据库出错的问题
2005
不能附加经过2008附加过的数据库(2008附加会有一个升级的过程,升级后不能降级)
也不能用备份+还原的方式解决问题
可以在2008中右键数据库--任务--生成脚本
通过脚本生成向导为整个库的对象生成脚本,并设置好相关的脚本生成选项,尤其要注意的是脚本的服务器版本要选择sql
server
2005
完成向导后,在2005中执行生成的脚本,这样就把2008的库结构搬到2005了
再用数据导入/导出向导把数据导过去就行了
转自:邹建
8. 学习SQL,看哪些资料比较好
《中文版SQL Server 2000开发与管理应用》 作者:邹建
SQL Server 2005 Transact-SQL编程入门经典 :(美)特里(Turley,P.),(美)伍德(Wood,D.) 着,刘颖 译
SQLServer 2005开发圣经 SQL Server2005系统管理实录 SQLServer 2005数据库开发详解(姚巧枚 胡百敬)
自己 挑吧
建议你先看看ACCSEE,建几个查询,看查询所对应的SQL视图,有个对照,知道什么语句有什么效果。
这些对你学习sql都有很大的帮助,不妨看看
9. sql server中利用sql语句如何创建角色和用户
, securityadmingo--作好SQL的安全管理--作者:邹建 首先,做好用户安全:--简单的,只允许sql的用户访问sql(防止利用administrator组用户访问)1 .企业管理器--右键SQL实例--属性--安全性--身份验证--选择"sql server和windows"--确定2 .企业管理器--安全性--登陆--右键sa--设置密码--其他用户也设置密码3 .删除用户:BUILTIN\Administrators<机器名 \Administrator--这个用户不一定有 这样可以防止用windows身份登陆SQL4 .设置进入企业管理器需要输入密码 在企业管理器中--右键你的服务器实例(就是那个有绿色图标的)--编辑SQL Server注册属性--选择"使用 SQL Server 身份验证"--并勾选"总是提示输入登录名和密码"--确定--经过上面的设置,你的SQL Server基本上算是安全了.------------------------------------------------------------------------ 其次,改默认端口,隐藏服务器,减少被攻击的可能性 SQL Server服务器--开始--程序--Microsoft SQL Server--服务器网络实用工具--启用的协议中"TCP/IP"--属性--默认端口,输入一个自已定义的端口,比如2433--勾选隐藏服务器------------------------------------------------------------------------------管好sql的用户,防止访问他不该访问的数据库(总控制,明细还可以控制他对于某个数据库的具体对象具有的权限)--切换到你新增的用户要控制的数据库use你的库名go--新增用户execsp_addlogin'test'--添加登录execsp_grantdbaccess N'test'--使其成为当前数据库的合法用户execsp_addrolemember N'db_owner' , N'test'--授予对自己数据库的所有权限--这样创建的用户就只能访问自己的数据库,及数据库中包含了guest用户的公共表go--删除测试用户execsp_revokedbaccess N'test'--移除对数据库的访问权限execsp_droplogin N'test'--删除登录 如果在企业管理器中创建的话,就用:企业管理器--安全性--右键登录--新建登录常规项--名称中输入用户名--身份验证方式根据你的需要选择(如果是使用windows身份验证,则要先在操作系统的用户中新建用户)--默认设置中,选择你新建的用户要访问的数据库名 服务器角色项 这个里面不要选择任何东西 数据库访问项 勾选你创建的用户需要访问的数据库名 数据库角色中允许,勾选"public ","db_ownew" 确定,这样建好的用户与上面语句建立的用户一样--------------------------------------------------------------------------- 最后一步,为具体的用户设置具体的访问权限,这个可以参考下面的最简示例:--添加只允许访问指定表的用户:execsp_addlogin'用户名','密码','默认数据库名'--添加到数据库execsp_grantdbaccess'用户名'--分配整表权限GRANTSELECT, INSERT, UPDATE, DELETEONtable1TO[用户名]--分配权限到具体的列GRANTSELECT, 至于具体的安全设置和理论知道,参考SQL联机帮助
10. sqlsever 2000 分页语句
CREATE PROCEDURE P_Page
(
@pageNo INT=1,
@pageSize INT=10
)
AS
DECLARE @s NVARCHAR(2000)
SET @s='SELECT top '+RTRIM(@pageSize)+'* FROM enterprise WHERE ID not in(select top '+RTRIM((@pageNo-1)*@pageSize)+' from enterprise)'
EXEC (@s)
go
可用存储过程,如以上ID为表唯一列时可调用
SQL2000可用邹建写法,最高效的写法还是针对性的写
楼主换SQL2005以上版本可用row_Number实现更简单
/*--用存储过程实现的分页程序
显示指定表、视图、查询结果的第X页
对于表中主键或标识列的情况,直接从原表取数查询,其它情况使用临时表的方法
如果视图或查询结果中有主键,不推荐此方法
--邹建 2003.09(引用请保留此信息)--*/
/*--调用示例
exec p_show '地区资料'
exec p_show '地区资料',5,3,'地区编号,地区名称,助记码','地区编号'
--*/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_show]') and OBJECTPROPERTY(id, N'IsProcere') = 1)
drop procere [dbo].[p_show]
GO
CREATE Proc p_show
@QueryStr nvarchar(4000), --表名、视图名、查询语句
@PageSize int=10, --每页的大小(行数)
@PageCurrent int=1, --要显示的页
@FdShow nvarchar (4000)='', --要显示的字段列表,如果查询结果有标识字段,需要指定此值,且不包含标识字段
@FdOrder nvarchar (1000)='' --排序字段列表
as
declare @FdName nvarchar(250) --表中的主键或表、临时表中的标识列名
,@Id1 varchar(20),@Id2 varchar(20) --开始和结束的记录号
,@Obj_ID int --对象ID
--表中有复合主键的处理
declare @strfd nvarchar(2000) --复合主键列表
,@strjoin nvarchar(4000) --连接字段
,@strwhere nvarchar(2000) --查询条件
select @Obj_ID=object_id(@QueryStr)
,@FdShow=case isnull(@FdShow,'') when '' then ' *' else ' '+@FdShow end
,@FdOrder=case isnull(@FdOrder,'') when '' then '' else ' order by '+@FdOrder end
,@QueryStr=case when @Obj_ID is not null then ' '+@QueryStr else ' ('+@QueryStr+') a' end
--如果显示第一页,可以直接用top来完成
if @PageCurrent=1
begin
select @Id1=cast(@PageSize as varchar(20))
exec('select top '+@Id1+@FdShow+' from '+@QueryStr+@FdOrder)
return
end
--如果是表,则检查表中是否有标识更或主键
if @Obj_ID is not null and objectproperty(@Obj_ID,'IsTable')=1
begin
select @Id1=cast(@PageSize as varchar(20))
,@Id2=cast((@PageCurrent-1)*@PageSize as varchar(20))
select @FdName=name from syscolumns where id=@Obj_ID and status=0x80
if @@rowcount=0 --如果表中无标识列,则检查表中是否有主键
begin
if not exists(select 1 from sysobjects where parent_obj=@Obj_ID and xtype='PK')
goto lbusetemp --如果表中无主键,则用临时表处理
select @FdName=name from syscolumns where id=@Obj_ID and colid in(
select colid from sysindexkeys where @Obj_ID=id and indid in(
select indid from sysindexes where @Obj_ID=id and name in(
select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID
)))
if @@rowcount>1 --检查表中的主键是否为复合主键
begin
select @strfd='',@strjoin='',@strwhere=''
select @strfd=@strfd+',['+name+']'
,@strjoin=@strjoin+' and a.['+name+']=b.['+name+']'
,@strwhere=@strwhere+' and b.['+name+'] is null'
from syscolumns where id=@Obj_ID and colid in(
select colid from sysindexkeys where @Obj_ID=id and indid in(
select indid from sysindexes where @Obj_ID=id and name in(
select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID
)))
select @strfd=substring(@strfd,2,2000)
,@strjoin=substring(@strjoin,5,4000)
,@strwhere=substring(@strwhere,5,4000)
goto lbusepk
end
end
end
else
goto lbusetemp
/*--使用标识列或主键为单一字段的处理方法--*/
lbuseidentity:
exec('select top '+@Id1+@FdShow+' from '+@QueryStr
+' where '+@FdName+' not in(select top '
+@Id2+' '+@FdName+' from '+@QueryStr+@FdOrder
+')'+@FdOrder
)
return
/*--表中有复合主键的处理方法--*/
lbusepk:
exec('select '+@FdShow+' from(select top '+@Id1+' a.* from
(select top 100 percent * from '+@QueryStr+@FdOrder+') a
left join (select top '+@Id2+' '+@strfd+'
from '+@QueryStr+@FdOrder+') b on '+@strjoin+'
where '+@strwhere+') a'
)
return
/*--用临时表处理的方法--*/
lbusetemp:
select @FdName='[ID_'+cast(newid() as varchar(40))+']'
,@Id1=cast(@PageSize*(@PageCurrent-1) as varchar(20))
,@Id2=cast(@PageSize*@PageCurrent-1 as varchar(20))
exec('select '+@FdName+'=identity(int,0,1),'+@FdShow+'
into #tb from'+@QueryStr+@FdOrder+'
select '+@FdShow+' from #tb where '+@FdName+' between '
+@Id1+' and '+@Id2
)
GO