
2012年4月18日
今天做了一个存储过程
可实现对人事基本资料表中的所有栏位进行check,若有变化,则显示出来
参数:emp_id
原理:在服务器上有两个数据库备份,对比 emp_info 这两张表中相同emp_id的记录 ,
若某一列值不同,则显示出来。
主要问题点:
1.若不能用 OPENDATASOURCE,则可以通过以下sql开启权限。
- exec sp_configure 'show advanced options',1
- reconfigure
- exec sp_configure 'Ad Hoc Distributed Queries',1
- reconfigure
使用完成后,关闭Ad Hoc Distributed Queries:
- exec sp_configure 'Ad Hoc Distributed Queries',0
- reconfigure
- exec sp_configure 'show advanced options',0
- reconfigure
2.对比时,注意栏位编码不同,需要使用 COLLATE Chinese_PRC_CI_AS
3.对比时,需要注意对栏位null值的处理。
4.动态sql的使用。
USE [EasyHRO_ContinentalChina_20120222]
GO
/****** Object: StoredProcedure [dbo].[sp_get_emp_info_diff] Script Date: 04/18/2012 13:27:25 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[sp_get_emp_info_diff]
@emp_id nvarchar(50)
--WITH ENCRYPTION
AS
BEGIN
/*
select *
from
OPENDATASOURCE('SQLOLEDB','Data Source=CDPR9B0B6A;User ID=sa;Password=Init1234').EasyHRO_ContinentalChina_20120221.[dbo].[emp_info] a
where emp_id=@emp_id
select distinct xtype from dbo.syscolumns where id=object_id('emp_info') and name not in('emp_id','emp_workid')
select * from systypes
where systypes.xusertype in(56,59,61,104,231)
*/
declare @col_name nvarchar(20);
declare @col_type_id int;
if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..#tb') and type='U')
begin
drop table #tempcitys
end
create table #tb(emp_id int ,
emp_workid nvarchar(200) ,
emp_name nvarchar(200),
old_valus nvarchar(200),
new_valus nvarchar(200),
[col_name] nvarchar(200),
col_cname nvarchar(200)
)
declare cur cursor fast_forward for
select name,xusertype from dbo.syscolumns where id=object_id('emp_info') and name not in('emp_id','emp_workid');
open cur;
fetch next from cur into @col_name,@col_type_id;
while @@fetch_status=0
begin
--做你要做的事
DECLARE @dongtaisql nVARCHAR(4000);
if(@col_type_id=231)--nvarchar
begin
set @dongtaisql = 'insert into #tb select a.emp_id,a.emp_workid,a.emp_name,a.'+@col_name+',b.'+@col_name+','''+@col_name+''','''' from emp_info a,'
+' OPENDATASOURCE(''SQLOLEDB'',''Data Source=CDPR9B0B6A;User ID=sa;Password=Init1234'').EasyHRO_ContinentalChina_20120221.[dbo].[emp_info] b '
+' where a.emp_id=b.emp_id and isnull(a.'+@col_name+','''')<>isnull(b.'+@col_name +','''') COLLATE Chinese_PRC_CI_AS '
+' and a.emp_id=@emp_id '
--+' and a.emp_id='+QUOTENAME(@emp_id, '''')
end
else if(@col_type_id=56 or @col_type_id=59 or @col_type_id=104)--int,real,bit
begin
set @dongtaisql = ' insert into #tb select a.emp_id,a.emp_workid,a.emp_name,a.'+@col_name+',b.'+@col_name+','''+@col_name+''','''' from emp_info a,'
+' OPENDATASOURCE(''SQLOLEDB'',''Data Source=CDPR9B0B6A;User ID=sa;Password=Init1234'').EasyHRO_ContinentalChina_20120221.[dbo].[emp_info] b '
+' where a.emp_id=b.emp_id and isnull(a.'+@col_name+',0)<>isnull(b.'+@col_name+',0) '
+' and a.emp_id=@emp_id '
--+' and a.emp_id='+QUOTENAME(@emp_id, '''')
end
else if(@col_type_id=61)--datetime
begin
set @dongtaisql = ' insert into #tb select a.emp_id,a.emp_workid,a.emp_name,a.'+@col_name+',b.'+@col_name+','''+@col_name+''','''' from emp_info a,'
+' OPENDATASOURCE(''SQLOLEDB'',''Data Source=CDPR9B0B6A;User ID=sa;Password=Init1234'').EasyHRO_ContinentalChina_20120221.[dbo].[emp_info] b '
+' where a.emp_id=b.emp_id and isnull(a.'+@col_name+',''1900-01-01'')<>isnull(b.'+@col_name+',''1900-01-01'') '
+' and a.emp_id=@emp_id '
--+' and a.emp_id='+QUOTENAME(@emp_id, '''')
end
else
begin
set @dongtaisql = ' insert into #tb select a.emp_id,a.emp_workid,a.emp_name,CONVERT(nvarchar(10),a.'+@col_name+',112),CONVERT(nvarchar(10),b.'+@col_name+',112),'''+@col_name+''','''' from emp_info a,'
+' OPENDATASOURCE(''SQLOLEDB'',''Data Source=CDPR9B0B6A;User ID=sa;Password=XXXX'').EasyHRO_ContinentalChina_20120221.[dbo].[emp_info] b '
+' where a.emp_id=b.emp_id and a.'+@col_name+'<>b.'+@col_name
+' and a.emp_id=@emp_id '
--+' and a.emp_id='+QUOTENAME(@emp_id, '''')
end
print @dongtaisql
--exec @dongtaisql
--insert into #tb
EXEC SP_EXECUTESQL @dongtaisql, N'@emp_id nvarchar(50)',@emp_id
-- exec(
--'select a.emp_id,a.emp_workid,a.emp_name,a.'+@col_name+',b.'+@col_name+' from emp_info a,'
--+' OPENDATASOURCE(''SQLOLEDB'',''Data Source=CDPR9B0B6A;User ID=sa;Password=XXXX'').EasyHRO_ContinentalChina_20120221.[dbo].[emp_info] b '
--+' where a.emp_id=b.emp_id and a.'+@col_name+'<>b.'+@col_name
--+' and a.emp_id='+cast(@emp_id as nvarchar)+' ')
fetch next from cur into @col_name,@col_type_id;
end
close cur;
deallocate cur;
delete from #tb
where emp_id is null
update #tb
set col_cname=
(case when exists(select pla_lan_001 from pla_language
where pla_lan_code =[col_name] COLLATE Chinese_PRC_CI_AS and comp_lvcode=10001000)
then (select pla_lan_001 from pla_language
where pla_lan_code =[col_name] COLLATE Chinese_PRC_CI_AS and comp_lvcode=10001000)
else
(select pla_lan_001 from pla_language
where pla_lan_code =[col_name] COLLATE Chinese_PRC_CI_AS and comp_lvcode=1)
end
)
select emp_id,emp_workid,
emp_name,
case when isdate(old_valus)=1 then CONVERT(nvarchar(10),old_valus,121) else old_valus end as old_valus,
case when isdate(new_valus)=1 then CONVERT(nvarchar(10),new_valus,121) else new_valus end as new_valus,
[col_name],
col_cname
from #tb
/*
select a.emp_id,a.emp_workid,a.emp_name,a.emp_actid,b.emp_actid from emp_info a,
OPENDATASOURCE('SQLOLEDB','Data Source=CDPR9B0B6A;User ID=sa;Password=Init1234').EasyHRO_ContinentalChina_20120221.[dbo].[emp_info] b
where a.emp_id=b.emp_id and a.emp_actid<>b.emp_actid
and a.emp_id=@emp_id
*/
END
posted @ 2012-04-18 15:31 black263 阅读(2) 评论(0)
编辑
刚写的存储过程,保存一下,^_^
CREATE PROCEDURE dbo.Trans_GetTableColumnsInfo
@TableName varchar(50)
/*
根据传入的表名,获取对应表的列的信息,列名,列数据类型,数据类型长度,列是否是主键列
*/
AS
/*
获取该表的主键列的列名,保存在@ColName中
*/
declare @Sql nvarchar(200)
declare @ColName varchar(50)
set @Sql=N'select @ColName=name from syscolumns where exists(select id,indid from sysindexes wherename=''PK_'+@TableName+''' and syscolumns.id=sysindexes.id and syscolumns.colid=sysindexes.indid)'
exec sp_executesql @Sql,N'@ColName varchar(50) out',@ColName out
/*
获取该表的列信息,列名,列数据类型,列数据类型长度,列是否是主键列
*/
select syscolumns.name as ColName,systypes.name as ColType,syscolumns.length as ColLength,case syscolumns.name when @ColName then 1 else 0 end as IsPkColumn
from syscolumns join sysobjects on syscolumns.id=sysobjects.id join systypes on systypes.xtype=syscolumns.xtype
where sysobjects.name=@TableName
GO
---------------------------------------
简单获取主键列名,可以这样:
sp_pkeys 'youtable'
就可以得到你想要的主鍵字段的值
posted @ 2012-04-18 14:44 black263 阅读(12) 评论(0)
编辑
原因:在从远程服务器复制数据到本地时出现“SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDatasource' 的访问,因为此组件已作为此服务器安全配置的一部分而被关闭。系统管理员可以通过使用 sp_configure 启用 'Ad Hoc Distributed Queries'。有关启用 'Ad Hoc Distributed Queries' 的详细信息 ”错误,因此网上搜索,发现以下解决方法:
启用Ad Hoc Distributed Queries:
- exec sp_configure 'show advanced options',1
- reconfigure
- exec sp_configure 'Ad Hoc Distributed Queries',1
- reconfigure
使用完成后,关闭Ad Hoc Distributed Queries:
- exec sp_configure 'Ad Hoc Distributed Queries',0
- reconfigure
- exec sp_configure 'show advanced options',0
- reconfigure
本人验证成功:
后查询SQL联机丛书,MSDN官方为下以内容:
默认情况下,SQL Server并不允许专案分布式查询使用OPENROWSET和OPENDATASOURCE。 When this option is set to 1, SQL Server allows ad hoc access.当这个选项被设置为1,SQL Server允许即席访问。 When this option is not set or is set to 0, SQL Server does not allow ad hoc access.当此选项未设置或设置为0,SQL Server不允许即席访问。
Ad hoc distributed queries use the OPENROWSET and OPENDATASOURCE functions to connect to remote data sources that use OLE DB.特设分布式查询使用OPENROWSET和OPENDATASOURCE函数连接到远程数据源,使用OLE DB。 OPENROWSET and OPENDATASOURCE should be used only to reference OLE DB data sources that are accessed infrequently. OPENROWSET和OPENDATASOURCE应该只用于引用OLE DB数据源很少访问。 For any data sources that will be accessed more than several times, define a linked server.将会比多次访问的任何数据源,定义链接服务器。
Security Note 安全注意事项
Enabling the use of ad hoc names means that any authenticated login to SQL Server can access the provider.启用使用的专案名称,意味着任何身份验证登录到SQL Server可以访问的供应商。 SQL Server administrators should enable this feature for providers that are safe to be accessed by any local login. SQL Server管理员应该启用此功能为供应商,安全,可以由任何本地登录访问。 For more information, see the DisallowAdhocAccess option in Accessing External Data .欲了解更多信息,请参阅在访问外部数据 的DisallowAdhocAccess选项
http://msdn.microsoft.com/en-us/library/ms187569.aspx
特此MARK!!!
转自http://blog.csdn.net/bard_j/article/details/6711661
posted @ 2012-04-18 14:35 black263 阅读(7) 评论(0)
编辑

2012年3月8日
原文地址:http://topic.csdn.net/u/20100317/15/04f1bf02-48be-4567-be7f-22c0ec5d2df9.html 13#,16#
create function dbo.GetFormatString(@dec decimal(28,15), @n int)
returns nvarchar(32) as
BEGIN
--原理,用parsename切成整数部分和小数部分(去除最后的0)
--用convert转money,自动带千分位
declare @re nvarchar(32)
declare @a nvarchar(32),@b nvarchar(32)
select @dec=round(@dec, case when @n<0 then 0 when @n=0 then 15 else @n end)
select @a=case when parsename(rtrim(@dec),2)='' then '0' else parsename(rtrim(@dec),2) end,
@b=parsename(rtrim(@dec),1)
select @a= parsename(convert(nvarchar(32), convert(money,@a),1),2)
select @b= stuff(reverse(@b),1,case when patindex('%[1-9]%',reverse(@b))>1 then patindex('%[1-9]%',reverse(@b))-1 else len(@b) end ,'' )
--小数部分加千分位
--select @b=reverse( parsename(convert(nvarchar(32), convert(money,@b),1),2))
--if @b='0' and @n>0
-- set @b=left('000,000,000,000,000', @n+(@n-1)/3)
--小数部分不加千分位
select @b=reverse(@b)
if @b='0' and @n>0
set @b=left('000000000000000', @n)
select @re= case when @n>=0 then @a+'.'+@b else @a end
if @b='0' and @n=0
set @re=@a
return @re
END
posted @ 2012-03-08 14:42 black263 阅读(21) 评论(0)
编辑