Profile'"&PhotosBlogLists Tools Help
October 19

远程数据库查询 OPENROWSET


包含访问 OLE DB 数据源中的远程数据所需的全部连接信息。当访问链接服务器中的表时,这种方法是一种替代方法,并且是一种使用 OLE DB 连接并访问远程数据的一次性的、特殊的方法。可以在查询的 FROM 子句中像引用表名那样引用 OPENROWSET 函数。依据 OLE DB 提供程序的能力,还可以将 OPENROWSET 函数引用为 INSERT、UPDATE 或 DELETE 语句的目标表。尽管查询可能返回多个结果集,然而 OPENROWSET 只返回第一个。

语法
OPENROWSET ( 'provider_name'
    , { 'datasource' ; 'user_id' ; 'password'
        | 'provider_string' }
    , { [ catalog.] [ schema.] object
        | 'query' }
    )

参数
'provider_name'

字符串,它代表在注册表中指定的 OLE DB 提供程序的友好名。provider_name 没有默认值。

'datasource'

字符串常量,它对应着某个特定的 OLE DB 数据源。datasource 是将被传递到提供程序 IDBProperties 接口以初始化提供程序的 DBPROP_INIT_DATASOURCE 属性。通常,这个字符串包含数据库文件的名称、数据库服务器的名称,或者提供程序能理解的用于查找数据库的名称。

'user_id'

字符串常量,它是传递到指定 OLE DB 提供程序的用户名。user_id 为连接指定安全上下文,并将它作为 DBPROP_AUTH_USERID 属性传递进来以初始化提供程序。

'password'

字符串常量,它是将被传递到 OLE DB 提供程序的用户密码。当初始化提供程序时,将 password 作为 DBPROP_AUTH_PASSWORD 属性传递进来。

'provider_string'

提供程序特定的连接字符串,将它作为 DBPROP_INIT_PROVIDERSTRING 属性传递进来以初始化 OLE DB 提供程序。通常 provider_string 封装初始化提供程序所需的所有连接信息。

catalog

目录或数据库的名称,其中驻留着指定的对象。

schema

架构的名称或指定对象的对象所有者名称。

object

对象名称,它唯一地标识出将要操作的对象。

'query'

是字符串常量,发送到提供程序并由提供程序执行。Microsoft® SQL Server™ 不处理该查询,但处理由提供程序返回的查询结果(直接传递查询)。对于有些提供程序,它们并没有通过表名而是通过命令语言表现自己的表格格式数据,那么将直接传递查询用于这些提供程序是非常有用的。只要查询提供程序支持 OLE DB Command 对象及其强制接口,那么在远程服务器上就支持直接传递查询。有关更多信息,请参见 SQL Server OLE DB 程序员参考。

注释
如果 OLE DB 提供程序在指定的数据源中支持多个目录和架构,那么就需要目录及架构名称。如果 OLE DB 提供程序并不支持目录和架构,那么可以省略 catalog 及 schema 的值。

如果提供程序只支持架构名,那么必须指定一个两部分名称,形式为 schema.object。如果提供程序只支持目录名,那么必须指定一个三部分名称,形式为 catalog.schema.object。

OPENROWSET 不接受参数变量。

权限
OPENROWSET 权限由传递到 OLE DB 提供程序的用户名的权限确定。

示例
A. 将 OPENROWSET 与 SELECT 语句及用于 SQL Server 的 Microsoft OLE DB 提供程序一起使用
下面的示例使用用于 SQL Server 的 Microsoft OLE DB 提供程序访问 pubs 数据库中的 authors 表,该数据库在一个名为 seattle1 的远程服务器上。从 datasource、user_id 及 password 中初始化提供程序,并且使用 SELECT 语句定义返回的行集。

USE pubs
GO
SELECT a.*
FROM OPENROWSET('SQLOLEDB','seattle1';'sa';'MyPass',
   'SELECT * FROM pubs.dbo.authors ORDER BY au_lname, au_fname') AS a
GO

 

sql server中分布式查询




由于业务逻辑的多样性
经常得在sql server中查询不同数据库中数据
这就产生了分布式查询的需求

现我将开发中遇到的几种查询总结如下:


1.access版本

--建立连接服务器
EXEC sp_addlinkedserver
--要创建的链接服务器名称 
'ai',            
--产品名称              
'access',    
--OLE DB 字符
'Microsoft.Jet.OLEDB.4.0', 
--数据源
--格式:
-- 盘符:\路径\文件名
-- \\网络名\共享名\文件名  (网络版本)
'd:\testdb\db.mdb'
GO


--创建链接服务器上远程登录之间的映射
--链接服务器默认设置为用登陆的上下文进行
--现在我们修改为连接链接服务器不需使用任何登录或密码
exec sp_addlinkedsrvlogin 'ai','false'
go


--查询数据
select * from ai...mytable
go

2.excel版本

--建立连接服务器
EXEC sp_addlinkedserver
--要创建的链接服务器名称 
'ai_ex',            
--产品名称              
'ex',    
--OLE DB 字符
'Microsoft.Jet.OLEDB.4.0', 
--数据源
--格式:
-- 盘符:\路径\文件名
-- \\网络名\共享名\文件名  (网络版本)
'd:\testdb\mybook.xls' ,
null,
--OLE DB 提供程序特定的连接字符串
'Excel 5.0'
GO


----创建链接服务器上远程登录之间的映射
--链接服务器默认设置为用登陆的上下文进行
--现在我们修改为连接链接服务器不需使用任何登录或密码
exec sp_addlinkedsrvlogin 'ai_ex','false'
go


--查询数据
select * from ai_ex...sheet3$
go


3.ms sql版本

--建立连接服务器
EXEC sp_addlinkedserver
--要创建的链接服务器名称 
'ai_mssql',            
--产品名称              
'ms',    
--OLE DB 字符
'SQLOLEDB', 
--数据源
'218.204.111.111,3342'
GO


--创建链接服务器上远程登录之间的映射
EXEC sp_addlinkedsrvlogin
'ai_mssql',
'false',
NULL,
--远程服务器的登陆用户名
'zhangzhe',
--远程服务器的登陆密码
'fish2231'
go


--查询数据
select * from ai_mssql.pubs.dbo.jobs
go


--还有一个更简单的办法
--这种方式在链接服务器建立后,它是默认开放RPC的

--建立连接服务器
EXEC sp_addlinkedserver
--要创建的链接服务器名称
--这里就用数据源作名称
'218.204.111.111,3342',
'SQL Server'
GO


--创建链接服务器上远程登录之间的映射
EXEC sp_addlinkedsrvlogin
'218.204.111.111,3342',
'false',
NULL,
--远程服务器的登陆用户名
'zhangzhe',
--远程服务器的登陆密码
'fish2231'
go


--查询数据
select * from [218.204.253.131,3342].pubs.dbo.jobs
go

4.Oracle版本

--建立连接服务器
EXEC sp_addlinkedserver
--要创建的链接服务器名称 
'o',
--产品名称              
'Oracle',
--OLE DB 字符
'MSDAORA',
--数据源
'acc'
GO


--创建链接服务器上远程登录之间的映射
EXEC sp_addlinkedsrvlogin
'o',
'false',
NULL,
--Oracle服务器的登陆用户名
'F02M185',
--Oracle服务器的登陆密码
'f02m185185'
go

--查询数据
--格式:LinkServer..Oracle用户名.表名
--注意用大写,因为在Oracle的数据字典中为大写
select * from o..F02M185.AI
go

希望上面提到的知识对你有所提示
当然欢迎交流和指正

author:aierong
blog:http://www.cnblogs.com/aierong
email:aierong@126.com

October 07

数据库管理专才成功四步走

  南方网讯  信息技术时代,政府、企业的大量信息都存放在数据库中,于是专门负责建立、维护、开发这些数据库的管理人员就应运而生了。今天,政府和企业已经不满足于仅仅维持系统的高效率、低成本运行,他们期望通过信息的挖掘,为高层决策提供支持。因此,数据库管理与开发人才的作用越来越重要。
  数据库管理专才难觅
  RHI咨询公司执行董事凯瑟琳·斯潘塞·李认为:“精通Ora?鄄cle和微软SQL Server管理,并能把电子商务应用中收集到的大量数据转变成‘商业智能’的人员,越来越受到企业的青睐。” 什么叫“商业智能”?下面的例子也许能说明。
  美国沃尔玛超市的一位数据管理人员在进行信息整理时,意外地发现了一个数据联系:啤酒与尿布的销售成正比。这位数据管理员由此断定,很多父亲在给孩子买尿布的同时会捎上些啤酒。于是他建议在尿布旁边放上啤酒。这样一来,尿布和啤酒的销量都在不经意间上升了。
  商业智能如此重要,但能将数据转化为商业智能的人才却不多见。在上海银河教育中心举行的数据库管理职业前景说明会上,数据库管理专家李耿告诉记者,目前市场中的数据库管理人才主要由软件专业应届毕业生或其他专业的人才转行而来,接受过系统化数据库管理培训和认证的人员相对较少,多数人对各种数据库管理的工具与产品认识不足,实际操作能力欠缺。可以说,市场对这类人才需求日益增大,但现有人员不能完全满足需要。
  如何从新人成长为专才
  数据库管理是最近几年兴起的职业,由于人才紧缺,其平均收入在IT领域居于高端。据统计,持有MCDBA(微软认证数据库管理员)证书的IT专业人员要比持有MCP、MCSE的专业人员的平均年薪高出30—50%.
  高薪使得很多人趋之若骛,但数据库管理是一项比较枯燥的工作,每天要面对浩如烟海的原始数据,通过对数据的整理、抽取、合并来获取有用信息。这个过程十分艰难,何况不一定每次都能获取有用信息,甚至有时会获取一组“垃圾”。因此,从事数据库管理,一定要对这份工作怀有强烈的愿望和热爱,这样才能保证原始的工作热情,否则很难在这个行业坚持下去。
  座右铭:要为你热爱的东西而工作,或者学会热爱你的工作。
  第二步:寻找合适的工作平台
  数据库管理是一个复杂的系统工程,想进入这个领域,知识准备固然重要,经验准备更加关键。要想成为优秀的数据库管理人员,一定要去应聘那些真正依赖于数据库管理的大型企业或机构。一般而言,政府机构中的劳动局、建设局,以及电信、银行、证券等几类企业对数据库管理的要求比较高。进入这些企业或机构,你才有机会参与大型数据处理项目,接触到一些数据库管理的初步工作。当然,如果有幸进入专业的数据库管理公司,那你的专业能力一定会突飞猛进。
  座右铭:电信公司、证券公司、社保基金管理办公室……是你的就业方向。
  第三步:自我学习
  大学里掌握的软件知识不足以应付数据管理工作,自学是必不可少的步骤。学习可以分成两方面:一方面是技术上的学习。现在流行的数据库管理软件是Oracle和微软SQL Server,你必须对它们有足够的认识,并且能够熟练地运用。还要对各种辅助产品有相当的认识,明白进行什么任务时应该采用何种工具,如SPSS、INFOR?鄄MATICA、COGNOS等。另一方面是专业的学习。包括在整理数据方面的专业知识,如统计学的一些基本概念;还有就是与所从事业务相关的知识,比如要整理银行客户信息,你就必须了解银行会关心贷款申领人的哪些基本条件,年龄、基本收入、银行存款,婚否……这些要素在整理数据时一个都不能少。总之,数据库管理几乎是一个全新的职业,你必须天天学习,每天进步一点。
  座右铭:好好学习,天天向上。
  第四步:在团队中崭露头角
  一般而言,一个机构会由整个团队来完成信息系统管理的任务,并不设置专门的数据库管理人员。如果你刚刚进入这个团队,可能只做一些基础性质的工作。经过学习,经过团队中一定的磨练,你也可以毛遂自荐,在数据建模、数据开发、数据挖掘等方面主动承担一部分任务。这样,你就会在团队中树立起精通数据库管理的形象,而且能够积累实际操作经验。一旦有了真正的大项目,你就能大显身手了。
  座右铭:关键时刻,敢于充当“出头鸟”。
编辑:吕剑
September 22

为Project提供一个统一风格的DataGrid(转载)

基本上,一个Project中我们使用的控件风格都是一致的,比如DataGrid控件,他的页眉,页脚,行的字体颜色,交替行的背景色等等,我们不太可能每次使用这个控件都去设置一次这些属性,这绝对是一件很烦人的事。通常情况下我们会使用css来定义这些风格,然后再去分别定义DataGrid的ItemStyle,HeaderStyle等等的css属性,不过即便如此,几次这样的经历后,我还是觉得这实在是一件很烦人的事情,为什么不可以我不去设置这些风格属性,而他们每次都保持我所需要的风格呢?
通过继承标准DataGrid控件,可以来比较轻易的实现这个需求,我要做的就是读取某个xml文件或者config文件里面的样式设定(这种情况下一般不使用web.config文件,因为修改风格绝对是一件常见的事情,但是如果放入web.config中,每次修改web.config都引起应用程序重启,这可不太好.)
由于只涉及风格的显示,因此只需要重载OnPreRender

如下面类似的代码:

if(cache["TSDataGridConfig"] == null) { try { string configFilePath = HttpContext.Current.Server.MapPath (HttpContext.Current.Request.ApplicationPath) ; configFilePath += "\\" + ConfigFilePath; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(configFilePath); XmlNodeList nodeList = xmlDoc.SelectNodes("SiteConfig/TSDataGrid")[0].ChildNodes; Hashtable configTable = Hashtable.Synchronized(new Hashtable()); for(int i = 0,j = nodeList.Count; i < j;i++) { //只过滤Element节点,去掉其他节点,例如Comment if(nodeList[i].NodeType == XmlNodeType.Element) configTable.Add(nodeList[i].Name,nodeList[i].InnerText); } cache.Insert("TSDataGridConfig",configTable,new CacheDependency(configFilePath)); } catch { return; } } if(cache["TSDataGridConfig"] != null) {...}

   if(cache["TSDataGridConfig"] != null){...}

这段代码中作的就是从一个.config文件中读取了相关的配置节,并且存入Cache中,一旦修改了.config文件,则立即重新读取,接下来在if(cache["TSDataGridConfig"] != null){}块中要做的就是将对应的配置节点的值设置到DataGrid的相关属性,例如:
//AlternatingItem-BackColor if(CheckItem(configList["AlternatingItem-BackColor"])) base.AlternatingItemStyle.BackColor = Color.FromName((string)configList["AlternatingItem-BackColor"]); //CheckItem主要是判断AlternatingItem-BackColor是不是null或者值是不是String.Empty,如果是,就不设置

基本上我们已经可以使用这个控件来代替原来的标准DataGrid了,末了,还有一件比较浪费体力的事情,那就是DataGrid项的删除确认,因此可以继续在这里重载OnItemDataBound,类似代码如下:
if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { if((e.Item.FindControl("lbtnDelete") != null && e.Item.FindControl("lbtnDelete").GetType().ToString() == "System.Web.UI.WebControls.LinkButton")) ((LinkButton)e.Item.FindControl("lbtnDelete")).Attributes["onclick"] = "return confirm('即将删除指定项,确认?')"; } base.OnItemDataBound(e);
这里,我将删除的LinkButton ID假定为lbtnDelete,当然可以公开成一个属性了,不过我比较懒,因为我们还可以继续在调用页重载这个事件,如果我们确实需要的话....这样只要调用页用来执行删除Command的LinkButton Id为lbtnDelete,将会自动触发删除确认,不需要我们每次都去重复编写这段代码了.

DataGrid风格配置节片断:
#F9FFED ....

浅析《ASP.Net Web 站点高级编程》的登录验证!

博客园推荐网友Hover浅析《ASP.Net Web 站点高级编程》的登录验证!

 

ASP.NET 中内置的用户验证支持的功能非常强大,它能够自动地在Context对象中生成一个名为User的属性.
该属性能够让我们访问各种信息,包括用户是否已经验证。验证用户的类型,甚至还有用户名,不管我们是
使用基于表单的验证还是WINDOWS验证,都可以使用由Context对象表示的当前的HttpContext实例中的User对象

.Net FrameWork中提供的Context.User对象与前面介绍的User类不同。Context.User用于验证,
而User类用于某个用户的一般性信息.

.Net(不只是ASP.NET)中的安全机制基于负责人(principal)的概念,Principal对象代表以其名义运行代码的用户的安全
环境,因此,如果我运行程序,负责人就是程序运行期间我的安全环境。低于负责人的级别是身份(identity)
身份代表执行代码的用户。因此,每一个负责人都有一个身份,这种通用的负责人和身份的概念用于基于表单
的验证。Windows验证,甚至在.Net编程的其他用于传递证书给Web站点和远程主机.我们决定不创建自己的安全系统
但是要使用自己的负责人和身份的概念,以便巧妙地吻合于Microsoft已有的安全体系..

以上引用《 ASP.NET Web站点高级编程—提出问题-设计方案-解决方案 》,以下简称ThePhile(工程名)

ThePhile的验证方式是实现了IPrincipal和Identity接口


HttpContext.User的对象必须实现 System.Security.Principal.Iprincipal接口.

IPrincipal 概述

公共属性
Identity 获取当前用户的标识。

公共方法
IsInRole 确定当前用户是否属于指定的角色。

公共属性Identity又必须实现System.Security.Principal.IIdentity 接口

IIdentity 概述

公共属性
AuthenticationType 获取所使用的身份验证的类型。
IsAuthenticated 获取一个值,该值指示是否验证了用户。
Name 获取当前用户的名称

只要实现了这IPrincipal和IIdentity两个接口.然后分配给HttpContext.User的对象.
就可以判断出是否验证过.IsAuthenticated.或者获取用户名称等.


在ThePhile工程中。继承IPrincipal接口的是PhilePrincipal类(通过HttpContext.User可用)
继承IIdentity接口的是SiteIdentity类(通过HttpContext.User.Identity可用)
注:偶手里的代码此类是叫SiteIdentity。而书上的是PhileIdentity。其实没什么只是个类名.


先来看看登录页位于Modules\User\Login.aspx

这中登录页的登陆按钮单击事件

private void Submit_Click(object sender, System.EventArgs e)
        {            
            PhilePrincipal newUser = PhilePrincipal.ValidateLogin( EmailAddress.Text, Password.Text );
            //这里验证用户.并实现IPrincipal和IIdentity接口
            
            if (newUser == null)
            {
                LoginResult.Text = "Login failed for " + EmailAddress.Text;
                LoginResult.Visible = true;
            }
            else
            {
                Context.User = newUser;
                FormsAuthentication.SetAuthCookie( EmailAddress.Text, true );                    
                Response.Redirect("/ThePhile/default.aspx");
                //登录成功、写Cookie。跳转
            }
        }


###修改用户接口来支持验证.
需要修改PhilePage类。
因为此类是Web页的基类.. 继承System.Web.UI.Page

using System;
using System.Web;
using System.Web.UI;
using System.Diagnostics;
using Wrox.WebModules;

using Wrox.WebModules.Accounts.Business;

namespace Wrox.ThePhile.Web
{
    /**////
    /// Summary description for PhilePage.
    ///
    public class PhilePage : System.Web.UI.Page
    {                
        public PhilePage()
        {
        }

        protected override void OnInit(EventArgs e)
        {
            //这里重写了OnInit方法
            base.OnInit(e);
            this.Load += new System.EventHandler(this.PhilePage_Load);
            this.Error += new System.EventHandler(this.PhilePage_Error);
        }
            
        /**////这个是写事件日志方法
        protected void LogEvent(string message, EventLogEntryType entryType)
        {
            if (!EventLog.SourceExists("ThePhile.COM"))
            {
                EventLog.CreateEventSource("ThePhile.COM", "Application");
            }
            EventLog.WriteEntry("ThePhile.COM", message, entryType);
        }
        
        /**//// <summary>
        /// 捕获错误显示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void PhilePage_Error(object sender, System.EventArgs e)
        {
            string errMsg;
            Exception currentError = Server.GetLastError();

            errMsg = "<link rel=\"stylesheet\" href=\"/ThePhile/Styles/ThePhile.CSS\">";
            errMsg += "\<h1>Page Error\</h1><hr/>An unexpected error has occurred on this page. The system " +
                "administrators have been notified. Please feel free to contact us with the information " +
                "surrounding this error.<br/>"+
                "The error occurred in: "+Request.Url.ToString()+"<br/>"+
                "Error Message: <font class=\"ErrorMessage\">"+ currentError.Message.ToString() + "</font><hr/>"+
                "<b>Stack Trace:</b><br/>"+
                currentError.ToString();

            if ( !(currentError is AppException) )
            {
                // It is not one of ours, so we cannot guarantee that it has been logged
                // into the event log.
                LogEvent( currentError.ToString(), EventLogEntryType.Error );
            }

            Response.Write( errMsg );
            Server.ClearError();
        }

        
        private void PhilePage_Load(object sender, System.EventArgs e)
        {
            // TODO: Place any code that will take place BEFORE the Page_Load event
            // in the regular page, e.g. cache management, authentication verification,
            // etc.                                            
            if (Context.User.Identity.IsAuthenticated)
            {
                        //如果是验证通过的
                    
                if (!(Context.User is PhilePrincipal))
                {
                    // ASP.NET's regular forms authentication picked up our cookie, but we
                    // haven't replaced the default context user with our own. Let's do that
                    // now. We know that the previous context.user.identity.name is the e-mail
                    // address (because we forced it to be as such in the login.aspx page)                
                    PhilePrincipal newUser = new PhilePrincipal( Context.User.Identity.Name );
                    Context.User = newUser;
                }
                //此处是当前的Context.User不是PihlePrincipal的。转换一下
                //再赋给Context.User
            }
        }
    
    }
}

上面是PhilePage类。在Web页调用时继承一下就行了
此处有一个问题。当ASPX页继承此类时。
Web 窗体设计器生成的代码#region Web 窗体设计器生成的代码
        override protected void OnInit(EventArgs e)
        {
            //
            // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
            //
            InitializeComponent();
            base.OnInit(e);
        }
        
        /**//// <summary>
        /// 设计器支持所需的方法 - 不要使用代码编辑器修改
        /// 此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {    
            this.Load += new System.EventHandler(this.Page_Load);
        }
        #endregion

请看OnInit方法。是选调用了InitializeComponent()后调用父类的base.OnInit(e)
呵。这里可折腾了好几天。如果这样的话就在页面载入是先调用的是本页的Page_Load()方法
后调用父类的OnInit(e),这样PhilePage的Phile_Load()就形同虚设了。
在Thephile工程中它的页面的OnInit都是base.OnInit(e)在前面.而如果你新建一个页面的话就是在后面了
这可能与.Net版本有关。在书的封面上有Writeen and tested for final release of .Net V1.0
我这没有.Net v1.0所以也无法测试了。所以现在用2003 Vs.Net 的IDe时新建的页想要继承PhilePage需要把这两个方法的默认顺序手动改一下.

再看siteHeader控件.是通过验证显示用户名相关信息。否则显示未登录信息


private void Page_Load(object sender, System.EventArgs e)
        {
            // Put user code to initialize the page here
            Greeting.Text = "Welcome, ";
            /**////是否验证过
            if (Context.User.Identity.IsAuthenticated)
            {
                Greeting.Text += "<b>" + Context.User.Identity.Name + "</b>";
                UserLink.Text = "My Account";
                UserLink.NavigateUrl = "/ThePhile/Modules/Users/MyAccount.aspx";
                SignOut.Visible = true;
            }
            else
            {
                Greeting.Text += "Guest User.";
                UserLink.Text = "Click to Login";
                UserLink.NavigateUrl = "/ThePhile/Modules/Users/Login.aspx";
                SignOut.Visible = false;
            }        
        }
            /**////这是退出
        private void SignOut_Click(object sender, System.EventArgs e)
        {
            FormsAuthentication.SignOut();
            Response.Redirect("/thephile");
        }
这样就实现了登录验证。这里一定要注意的地方是。呵要先启用Forms验证方可使上面的代码奏效

<identity impersonate="true" />
    <!--  AUTHENTICATION
          This section sets the authentication policies of the application. Possible modes are "Windows", "Forms",
          "Passport" and "None"
    -->
    <authentication mode="Forms">
        <forms name="ThePhile" path="/" loginUrl="/ThePhile/Modules/Users/Login.aspx"
            protection="All" timeout="30">
        </forms>
    </authentication>

具体的代码请参看ThePhile.早就应该写了。出于自己懒。一看12月快过了一个随笔都没有可不行。
急急忙瞎写了一大堆。有错误和不妥地方请大家见谅!

 

 

 
Photo 1 of 1