Feed on
Posts
Comments
触发器是特殊的存储过程,存储过程需要程序调用,而触发器会自动执行;函数是根据输入产生输出。
 
在什么时候用触发器?要求系统根据某些操作自动完成相关任务,比如,根据买掉的产品的输入数量自动扣除该产品的库存量。什么时候用存储过程?存储过程就是程序,它是经过语法检查和编译的SQL语句,所以运行特别快。
 
存储过程和用户自定义函数具体的区别
先看定义:
存储过程
存储过程可以使得对数据库的管理、以及显示关于数据库及其用户信息的工作容易得多。存储过程是 SQL 语句和可选控制流语句的预编译集合,以一个名称存储并作为一个单元处理。存储过程存储在数据库内,可由应用程序通过一个调用执行,而且允许用户声明变量、有条件执行以及其它强大的编程功能。
存储过程可包含程序流、逻辑以及对数据库的查询。它们可以接受参数、输出参数、返回单个或多个结果集以及返回值。
可以出于任何使用 SQL 语句的目的来使用存储过程,它具有以下优点:
·                               可以在单个存储过程中执行一系列 SQL 语句。
·                               可以从自己的存储过程内引用其它存储过程,这可以简化一系列复杂语句。
·                               存储过程在创建时即在服务器上进行编译,所以执行起来比单个 SQL 语句快。
用户定义函数
函数是由一个或多个 Transact-SQL 语句组成的子程序,可用于封装代码以便重新使用。Microsoft? SQL Server? 2000 并不将用户限制在定义为 Transact-SQL 语言一部分的内置函数上,而是允许用户创建自己的用户定义函数。
可使用 CREATE FUNCTION 语句创建、使用 ALTER FUNCTION 语句修改、以及使用 DROP FUNCTION 语句除去用户定义函数。每个完全合法的用户定义函数名 (database_name.owner_name.function_name) 必须唯一。
必须被授予 CREATE FUNCTION 权限才能创建、修改或除去用户定义函数。不是所有者的用户在 Transact-SQL 语句中使用某个函数之前,必须先给此用户授予该函数的适当权限。若要创建或更改在 CHECK 约束、DEFAULT 子句或计算列定义中引用用户定义函数的表,还必须具有函数的 REFERENCES 权限。
在函数中,区别处理导致删除语句并且继续在诸如触发器或存储过程等模式中的下一语句的 Transact-SQL 错误。在函数中,上述错误会导致停止执行函数。接下来该操作导致停止唤醒调用该函数的语句。
用户定义函数的类型
SQL Server 2000 支持三种用户定义函数:
·                               标量函数
·                               内嵌表值函数
·                               多语句表值函数
用户定义函数采用零个或更多的输入参数并返回标量值或表。函数最多可以有 1024 个输入参数。当函数的参数有默认值时,调用该函数时必须指定默认 DEFAULT 关键字才能获取默认值。该行为不同于在存储过程中含有默认值的参数,而在这些存储过程中省略该函数也意味着省略默认值。用户定义函数不支持输出参数。
标量函数返回在 RETURNS 子句中定义的类型的单个数据值。可以使用所有标量数据类型,包括bigintsql_variant。不支持timestamp数据类型、用户定义数据类型和非标量类型(如tablecursor)。在 BEGIN…END 块中定义的函数主体包含返回该值的 Transact-SQL 语句系列。返回类型可以是除textntextimagecursortimestamp之外的任何数据类型。
表值函数返回table。对于内嵌表值函数,没有函数主体;表是单个 SELECT 语句的结果集。对于多语句表值函数,在 BEGIN…END 块中定义的函数主体包含 TRANSACT-SQL 语句,这些语句可生成行并将行插入将返回的表中。有关内嵌表值函数的更多信息,请参见内嵌用户定义函数。有关表值函数的更多信息,请参见返回 table 数据类型的用户定义函数。
BEGIN…END 块中的语句不能有任何副作用。函数副作用是指对具有函数外作用域(例如数据库表的修改)的资源状态的任何永久性更改。函数中的语句唯一能做的更改是对函数上的局部对象(如局部游标或局部变量)的更改。不能在函数中执行的操作包括:对数据库表的修改,对不在函数上的局部游标进行操作,发送电子邮件,尝试修改目录,以及生成返回至用户的结果集。
函数中的有效语句类型包括:
·                               DECLARE 语句,该语句可用于定义函数局部的数据变量和游标。
·                               为函数局部对象赋值,如使用 SET 给标量和表局部变量赋值。
·                               游标操作,该操作引用在函数中声明、打开、关闭和释放的局部游标。不允许使用 FETCH 语句将数据返回到客户端。仅允许使用 FETCH 语句通过 INTO 子句给局部变量赋值。
·                               控制流语句。
·                               SELECT 语句,该语句包含带有表达式的选择列表,其中的表达式将值赋予函数的局部变量。
·                               INSERTUPDATE DELETE 语句,这些语句修改函数的局部table变量。
·                               EXECUTE 语句,该语句调用扩展存储过程。
在查询中指定的函数的实际执行次数在优化器生成的执行计划间可能不同。示例为 WHERE 子句中的子查询唤醒调用的函数。子查询及其函数执行的次数会因优化器选择的访问路径而异。
用户定义函数中不允许使用会对每个调用返回不同数据的内置函数。用户定义函数中不允许使用以下内置函数:
@@CONNECTIONS
@@PACK_SENT
GETDATE
@@CPU_BUSY
@@PACKET_ERRORS
GetUTCDate
@@IDLE
@@TIMETICKS
NEWID
@@IO_BUSY
@@TOTAL_ERRORS
RAND
@@MAX_CONNECTIONS
@@TOTAL_READ
TEXTPTR
@@PACK_RECEIVED
@@TOTAL_WRITE
 
 
架构绑定函数
CREATE FUNCTION 支持 SCHEMABINDING 子句,后者可将函数绑定到它引用的任何对象(如表、视图和其它用户定义函数)的架构。尝试对架构绑定函数所引用的任何对象执行 ALTER DROP 都将失败。
必须满足以下条件才能在 CREATE FUNCTION 中指定 SCHEMABINDING
·                               该函数所引用的所有视图和用户定义函数必须是绑定到架构的。
·                               该函数所引用的所有对象必须与函数位于同一数据库中。必须使用由一部分或两部分构成的名称来引用对象。
·                               必须具有对该函数中引用的所有对象(表、视图和用户定义函数)的 REFERENCES 权限。
可使用 ALTER FUNCTION 删除架构绑定。ALTER FUNCTION 语句将通过不带 WITH SCHEMABINDING 指定函数来重新定义函数。
调用用户定义函数
当调用标量用户定义函数时,必须提供至少由两部分组成的名称:
SELECT *, MyUser.MyScalarFunction()FROM MyTable
可以使用一个部分构成的名称调用表值函数:
SELECT *FROM MyTableFunction()
然而,当调用返回表的 SQL Server 内置函数时,必须将前缀 :: 添加至函数名:
SELECT * FROM ::fn_helpcollations()
可在 Transact-SQL 语句中所允许的函数返回的相同数据类型表达式所在的任何位置引用标量函数,包括计算列和 CHECK 约束定义。例如,下面的语句创建一个返回 decimal 的简单函数:
CREATE FUNCTION CubicVolume– Input dimensions in centimeters   (@CubeLength decimal(4,1), @CubeWidth decimal(4,1),    @CubeHeight decimal(4,1) )RETURNS decimal(12,3) — Cubic Centimeters.ASBEGIN   RETURN ( @CubeLength * @CubeWidth * @CubeHeight )END
然后可以在允许整型表达式的任何地方(如表的计算列中)使用该函数:
CREATE TABLE Bricks   (    BrickPartNmbr   int PRIMARY KEY,    BrickColor      nchar(20),    BrickHeight     decimal(4,1),    BrickLength     decimal(4,1),    BrickWidth      decimal(4,1),    BrickVolume AS              (               dbo.CubicVolume(BrickHeight,                         BrickLength, BrickWidth)              )   )
dbo.CubicVolume 是返回标量值的用户定义函数的一个示例。RETURNS 子句定义由该函数返回的值的标量数据类型。BEGIN…END 块包含一个或多个执行该函数的 Transact-SQL 语句。该函数中的每个 RETURN 语句都必须具有一个参数,可返回具有在 RETURNS 子句中指定的数据类型(或可隐性转换为 RETURNS 中指定类型的数据类型)的数据值。RETURN 参数的值是该函数返回的值。
J2EE学习者越来越多,J2EE本身技术不断在发展,涌现出各种概念,本文章试图从一种容易理解的角度对这些概念向初学者进行解释,以便掌握学习J2EE学习方向。
首先我们需要知道Java和J2EE是两个不同概念,Java不只是指一种语言,已经代表与微软不同的另外一个巨大阵营,所以Java有时是指一种软件系统的流派,当然目前主要是.NET和Java两大主流体系。
J2EE可以说指Java在数据库信息系统上实现,数据库信息系统从早期的dBase、到Delphi/VB等C/S结构,发展到B/S(Browser浏览器/Server服务器)结构,而J2EE主要是指B/S结构的实现。
J2EE又是一种框架和标准,框架类似API、库的概念,但是要超出它们。如果需要详细了解框架,可先从设计模式开始学习。
J2EE是一个虚的大的概念,J2EE标准主要有三种子技术标准:WEB技术、EJB技术和JMS,谈到J2EE应该说最终要落实到这三个子概念上。
这三种技术的每个技术在应用时都涉及两个部分:容器部分和应用部分,Web容器也是指Jsp/Servlet容器,你如果要开发一个Web应用,无论是编译或运行,都必须要有Jsp/Servlet库或API支持(除了JDK/J2SE以外)。
Web技术中除了Jsp/Servlet技术外,还需要JavaBeans或Java Class实现一些功能或者包装携带数据,所以Web技术最初裸体简称为Jsp/Servlet+JavaBeans系统。
谈到JavaBeans技术,就涉及到组件构件技术(component),这是Java的核心基础部分,很多软件设计概念(设计模式)都是通过JavaBeans实现的。
JavaBeans不属于J2EE概念范畴中,如果一个JavaBeans对象被Web技术(也就是Jsp/Servlet)调用,那么JavaBeans就运行在J2EE的Web容器中;如果它被EJB调用,它就运行在EJB容器中。
EJB(企业JavaBeans)是普通JavaBeans的一种提升和规范,因为企业信息系统开发中需要一个可伸缩的性能和事务、安全机制,这样能保证企业系统平滑发展,而不是发展到一种规模重新更换一套软件系统。
至此,JavaBeans组件发展到EJB后,并不是说以前的那种JavaBeans形式就消失了,这就自然形成了两种JavaBeans技术:EJB 和POJO,POJO完全不同于EJB概念,指的是普通JavaBeans,而且这个JavaBeans不依附某种框架,或者干脆可以说:这个 JavaBeans是你为这个应用程序单独开发创建的。
J2EE应用系统开发工具有很多:如JBuilder、Eclipse等,这些IDE首先是Java开发工具,也就是说,它们首要基本功能是可以开发出JavaBeans或Java class,但是如果要开发出J2EE系统,就要落实到要么是Web技术或EJB技术,那么就有可能要一些专门模块功能(如eclipse需要 lomboz插件),最重要的是,因为J2EE系统区分为容器和应用两个部分,所以,在任何开发工具中开发J2EE都需要指定J2EE容器。
J2EE容器分为WEB容器和EJB容器,Tomcat/Resin是Web容器;JBoss是EJB容器+Web容器等,其中Web容器直接使用 Tomcat实现的。所以你开发的Web应用程序可以在上面两种容器运行,而你开发的Web+EJB应用则只可以在JBoss服务器上运行,商业产品 Websphere/Weblogic等和JBoss属于同一种性质。
J2EE容器也称为J2EE服务器,大部分时它们概念是一致的。
如果你的J2EE应用系统的数据库连接是通过JNDI获得,也就是说是从容器中获得,那么你的J2EE应用系统基本与数据库无关,如果你在你的J2EE 应用系统耦合了数据库JDBC驱动的配置,那么你的J2EE应用系统就有数据库概念色彩,作为一个成熟需要推广的J2EE应用系统,不推荐和具体数据库耦合,当然这其中如何保证J2EE应用系统运行性能又是体现你的设计水平了。
衡量J2EE应用系统设计开发水平高低的标准就是:解耦性;你的应用系统各个功能是否能够彻底脱离?是否不相互依赖,也只有这样,才能体现可维护性、可拓展性的软件设计目标。
为了达到这个目的,诞生各种框架概念,J2EE框架标准将一个系统划分为WEB和EJB主要部分,当然我们有时不是以这个具体技术区分,而是从设计上抽象为表现层、服务层和持久层,这三个层次从一个高度将J2EE分离开来,实现解耦目的。
因此,我们实际编程中,也要将自己的功能向这三个层次上靠,做到大方向清楚,泾渭分明,但是没有技术上约束限制要做到这点是很不容易的,因此我们还是必须借助J2EE具体技术来实现,这时,你可以使用EJB规范实现服务层和持久层,Web技术实现表现层;
EJB为什么能将服务层从Jsp/Servlet手中分离出来,因为它对JavaBeans编码有强制的约束,现在有一种对JavaBeans弱约束,使用Ioc模式实现的(当然EJB 3.0也采取这种方式),在Ioc模式诞生前,一般都是通过工厂模式来对JavaBeans约束,形成一个服务层,这也是是Jive这样开源论坛设计原理之一。
由此,将服务层从表现层中分离出来目前有两种可选架构选择:管理普通JavaBeans(POJO)框架(如Spring、 JdonFramework)以及管理EJB的EJB框架,因为EJB不只是框架,还是标准,而标准可以扩展发展,所以,这两种区别将来是可能模糊,被纳入同一个标准了。 但是,个人认为:标准制定是为某个目的服务的,总要牺牲一些换取另外一些,所以,这两种架构会长时间并存。
这两种架构分歧也曾经诞生一个新名词:完全POJO的系统也称为轻量级系统(lightweight),其实这个名词本身就没有一个严格定义,更多是一个吸引人的招牌,轻量是指容易学习容易使用吗?按照这个定义,其实轻量Spring等系统并不容易学习;而且EJB 3.0(依然叫EJB)以后的系统是否可称为轻量级了呢?
前面谈了服务层框架,使用服务层框架可以将JavaBeans从 Jsp/Servlet中分离出来,而使用表现层框架则可以将Jsp中剩余的JavaBeans完全分离,这部分JavaBeans主要负责显示相关,一般是通过标签库(taglib)实现,不同框架有不同自己的标签库,Struts是应用比较广泛的一种表现层框架。
这样,表现层和服务层的分离是通过两种框架达到目的,剩余的就是持久层框架了,通过持久层的框架将数据库存储从服务层中分离出来是其目的,持久层框架有两种方向:直接自己编写JDBC等SQL语句(如iBatis);使用O/R Mapping技术实现的Hibernate和JDO技术;当然还有EJB中的实体Bean技术。
持久层框架目前呈现百花齐放,各有优缺点的现状,所以正如表现层框架一样,目前没有一个框架被指定为标准框架,当然,表现层框架现在又出来了一个JSF,它代表的页面组件概念是一个新的发展方向,但是复杂的实现让人有些忘而却步。
在所有这些J2EE技术中,虽然SUN公司发挥了很大的作用,不过总体来说:网络上有这样一个评价:SUN的理论天下无敌;SUN的产品用起来撞墙;对于初学者,特别是那些试图通过或已经通过SUN认证的初学者,赶快摆脱SUN的阴影,立即开溜,使用开源领域的产品来实现自己的应用系统。
最后,你的J2EE应用系统如果采取上面提到的表现层、服务层和持久层的框架实现,基本你也可以在无需深刻掌握设计模式的情况下开发出一个高质量的应用系统了。
还要注意的是: 开发出一个高质量的J2EE系统还需要正确的业务需求理解,那么域建模提供了一种比较切实可行的正确理解业务需求的方法,相关详细知识可从UML角度结合理解。
当然,如果你想设计自己的行业框架,那么第一步从设计模式开始吧,因为设计模式提供你一个实现JavaBeans或类之间解耦参考实现方法,当你学会了系统基本单元JavaBean或类之间解耦时,那么系统模块之间的解耦你就可能掌握,进而你就可以实现行业框架的提炼了,这又是另外一个发展方向了。
以上理念可以总结为一句话:
J2EE开发三件宝: Domain Model(域建模)、patterns(模式)和framework(框架)。
推荐一套高质量的J2EE开源系统: JPestore

 

一、查看SQL Server 2005监听端口的方法

使用SQL:exec sys.sp_readerrorlog 0, 1, ‘listening’

显示结果如下:
LogDate  ProcessInfo Text
2009-05-21 15:08:14.590 服务器 Server is listening on [ ::1 <ipv6> 1026].
2009-05-21 15:08:41.730 服务器 Server is listening on [ 127.0.0.1 <ipv4> 1026].
2009-05-21 15:08:41.730 服务器 Dedicated admin connection support was established for listening locally on port 1026.
说明监听端口为1026。

二、修改SQL Server 2005 默认端口的方法
1、从开始->程序找到 Microsoft SQL Server 2005->配置工具->SQL Server Configuation Manager
2、展开SQL Server 2005网络配置,点击要配置的服务实例。
3、双击右边面板的协议名称:TCP/IP。
4、选择IP地址标签。在实际使用的IP地址下修改TCP端口,应用,确定。
5、点击SQL Server 2005 服务,在右边的面板右键刚配置的服务实例,重新启动。OK。

负载均衡技术

  网络的各个核心部分随着业务量的提高、访问量和数据流量的快速增长,其处理能力和计算强度也相应增大,使得单一设备 根本无法承担。在此情况下,如果扔掉现有设备去做大量的硬件升级,这样将造成现有资源的浪费,而且如果再面临下一次业务量的提升,这又将导致再一次硬件升 级的高额成本投入,甚至性能再卓越的设备也不能满足当前业务量的需求。于是,负载均衡机制应运而生。

  负载均衡(Load Balance)建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。

  负载均衡有两方面的含义:首先,大量的并发访问或数据流量分担到多台节点设备上分别处理,减少用户等待响应的时间;其次,单个重负载的运算分担到多台节点设备上做并行处理,每个节点设备处理结束后,将结果汇总,返回给用户,系统处理能力得到大幅度提高。

  什么是负载均衡

  负载均衡(Load Balance)

  由于目前现有网络的各个核心部分随着业务量的提高,访问量和数据流量的快速增长,其处理能力和计算强度也相应地增大,使得单一的服务器设备根本无法承担。在此情况下,如果扔掉现有设备去做大量的硬件升级,这样将造成现有资源的浪费,而且如果再面临下一次业务量的提升时,这又将导致再一次硬件升级的高额成本投入,甚至性能再卓越的设备也不能满足当前业务量增长的需求。

  针对此情况而衍生出来的一种廉价有效透明的方法以扩展现有网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性的技术就是负载均衡(Load Balance)。

  负载均衡技术主要应用

  1、DNS负载均衡 最早的负载均衡技术是通过DNS来实现的,在DNS中为多个地址配置同一个名字,因而查询这个名字的客户机将得到其中一个地址,从而使得不同的客户访问不同的服务器,达到负载均衡的目的。DNS负载均衡是一种简单而有效的方法,但是它不能区分服务器的差异,也不能反映服务器的当前运行状态。

  2、代理服务器负载均衡 使用代理服务器,可以将请求转发给内部的服务器,使用这种加速模式显然可以提升静态网页的访问速度。然而,也可以考虑这样一种技术,使用代理服务器将请求均匀转发给多台服务器,从而达到负载均衡的目的。

  3、地址转换网关负载均衡 支持负载均衡的地址转换网关,可以将一个外部IP地址映射为多个内部IP地址,对每次TCP连接请求动态使用其中一个内部地址,达到负载均衡的目的。

  4、协议内部支持负载均衡 除了这三种负载均衡方式之外,有的协议内部支持与负载均衡相关的功能,例如HTTP协议中的重定向能力等,HTTP运行于TCP连接的最高层。

  5、NAT负载均衡 NAT(Network Address Translation 网络地址转换)简单地说就是将一个IP地址转换为另一个IP地址,一般用于未经注册的内部地址与合法的、已获注册的Internet IP地址间进行转换。适用于解决Internet IP地址紧张、不想让网络外部知道内部网络结构等的场合下。

  6、反向代理负载均衡 普通代理方式是代理内部网络用户访问internet上服务器的连接请求,客户端必须指定代理服务器,并将本来要直接发送到internet上服务器的连接请求发送给代理服务器处理。反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。反向代理负载均衡技术是把将来自internet上的连接请求以反向代理的方式动态地转发给内部网络上的多台服务器进行处理,从而达到负载均衡的目的。

  7、混合型负载均衡在有些大型网络,由于多个服务器群内硬件设备、各自的规模、提供的服务等的差异,我们可以考虑给每个服务器群采用最合适的负载均衡方式,然后又在这多个服务器群间再一次负载均衡或群集起来以一个整体向外界提供服务(即把这多个服务器群当做一个新的服务器群),从而达到最佳的性能。我们将这种方式称之为混合型负载均衡。此种方式有时也用于单台均衡设备的性能不能满足大量连接请求的情况下。

代码的重用

 

面向对象的软件开发方式使得我们在分析之后,构建一个一个的对象,对象之间通过消息发生关系。这是一种非常自然的思维方式。通过对象的封装、继承和多态,使得我们最大程度地重用代码。各种组件及框架让我们的开发成为一种搭积木的过程。

然而面向对象仍然有问题,问题在于重用代码的方是。搭积木式的软件构造方法的基础是有许许多多各种各样的可重用的部件、模块。

一种重用的方式是类库,因为我们用面向对象的方法产生的直接结果就是许多的类。但类库的重用是基于源码的方式。你每次都必须重新编译,只有编译了才能与你自己的代码结合在一起生成可执行文件。在开发完成后,你的EXE都已经生成好了,如果这时侯你的类库发生了变化,那你就必须重新编译、重新调试!这离我们理想的积木式软件构造方法还有一定差距,在我们的设想里希望把一个模块拿出来再换一个新的模块是非常方便的事,可是现在不但要重新编译,还要冒着很大的风险,因为你可能要重新改变你自己的代码。

另一种重用方式很自然地就想到了是DLL的方式。Windows里到处是DLL,它是Windows 的基础,但DLL也有它自己的缺点。总结一下它至少有四点不足:

(1)函数重名问题。DLL里是一个一个的函数,我们通过函数名来调用函数,那如果两个DLL里有重名的函数怎么办?

(2)各编译器对C++函数的名称修饰不兼容问题。对于C++函数,编译器要根据函数的参数信息为它生成修饰名,DLL库里存的就是这个修饰名,但是不同的编译器产生修饰的方法不一样,所以你在VC 里编写的DLL在BC里就可以用不了。不过也可以用extern "C";来强调使用标准的C函数特性,关闭修饰功能,但这样也丧失了C++的重载多态性功能。

(3)路径问题。放在自己的目录下面,别人的程序就找不到,放在系统目录下,就可能有重名的问题。而真正的组件应该可以放在任何地方甚至可以不在本机,用户根本不需考虑这个问题。

(4)DLL与EXE的依赖问题。我们一般都是用隐式连接的方式,就是编程的时侯指明用什么DLL,这种方式很简单,它在编译时就把EXE与DLL绑在一起了。如果DLL发行了一个新版本,我们很有必要重新链接一次,因为DLL里面函数的地址可能已经发生了改变。

对于COM,它和DLL一样都是基于二进制的代码重用。同时,COM本身也是DLL,既使是ActiveX控件.ocx它实际上也是DLL,我们可以通过制订复杂的COM协议,通COM本身的机制改变了重用的方法,以一种新的方法来利用DLL,来克服DLL本身所固有的缺陷,从而实现更高一级的重用方法。

COM是通过虚函数表,没有重名问题,因为根本不是通过函数名来调用函数,自然也不会有函数名修饰的问题。路径问题也不复存在,因为是通过查注册表来找组件的,放在什么地方都可以。也不用考虑和EXE的依赖关系了,它们二者之间是松散的结合在一起,可以轻松的换上组件的一个新版本,而应用程序混然不觉。

C/C++:const VS #define

我们在C++中定义一个常量有两种语法:

格式1:#define MAX 100;
格式2:const int MAX = 100;

C++ 语言可以用const 来定义常量,也可以用 #define 来定义常量(也叫宏常量)。但是前者比后者有更多的优点:

(1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。

(2) 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。

结论:在C++ 程序中只使用const 常量而不使用宏常量,即const 常量完全取代宏常量。

另外需要注意的是不能在类声明中初始化const 数据成员。以下用法是错误的,因为类的对象未被创
建时,编译器不知道SIZE 的值是什么。
class A
{…
    const int SIZE = 100; // 错误,企图在类声明中初始化const 数据成员
    int array[SIZE]; // 错误,未知的SIZE
};

const 数据成员的初始化只能在类构造函数的初始化表中进行,例如
class A
{…
    A(int size); // 构造函数
   const int SIZE ;
};

A::A(int size) : SIZE(size) // 构造函数的初始化表
{

}

A a(100); // 对象 a 的SIZE 值为100
A b(200); // 对象 b 的SIZE 值为200

超车与超越

好久没有写日志的习惯了。
回过头来看看过去一年多的时间里,我惭愧地发现自己堕落的灵魂。曾经的意气风发,踌躇满志已经慢慢离我而去。

我承认环境会改变一个人。但平庸地活在,对一个人来说是一种耻辱。

今天早上依然无计划,无目的地去上班。在车上我意识到我这一年多以来的一个严重错误。

今天比平时起得要早一点,上班坐的是公交,虽然我一直很期待我能够有一辆自己的车,从容地行驶在这座城市的道路上,不用跟人挤或拼,但我似乎忘记了自己的梦想,梦想在不无行动,不执行中随风飘远。

这辆是私人的巴士,我一般很少坐这样的车。因为一般私人的巴士很少顾及乘客的利益,他们喜欢赖站,很少考虑别人是否上班迟到会被扣50大洋,或者别人是否有重要的事情要办,时间很紧。所以开车的与乘客会经常会发生言语上的不愉快,我对此已是屡见不鲜了,所以早有心理准备。

然而令我惊讶的是,这辆车在经过一个站A的时候竟然没有停车,原因是站A上有一辆同样的车,站上的乘客已经基本上挤上了那辆车。这辆车还对沿路站着招手的乘客也不理会,继续快速向前行驶。我很奇怪,这个车上还有空位,即使没有空位,只要还有块巴掌大的地方没有站人,他们一般都是随招随停的,似乎乘客在他们眼里就是一块一块的人民币,有谁看见有捡的钱不愿意捡呢?后面发生的情况让我明白了,他是想在下一站上更多的人,如果他停下来上一个人,或许下一站的乘客又成了对手的乘客。因为这两个车前后相聚不远,只要一停,就会被对方超车。一路上,他们就这样暗中较劲,一会你超我的车,一会我超你的车,速度都很快,让我吃惊的是,就这样在赛车的感觉中,我很快就到达目的地。

除了少数含着金匙出生的人外,多数人都会感觉到生活的压力和竞争的残酷,而我却如同温水里的青蛙,无聊地浮在水面,没有意识到水温在慢慢攀升。今天这两个车给我上了生动的一课:如果你不试图超越别人,那么别人就会超越你,也许该本该是你的,也会被人抢去。

 

在给定的系统硬件和系统软件条件下,提高数据库系统的运行效率的办法是:

(1) 在数据库物理设计时,降低范式,增加冗余, 少用触发器, 多用存储过程。

(2) 当计算非常复杂、而且记录条数非常巨大时(例如一千万条),复杂计算要先在数据库外面,以文件系统方式用编程语言计算处理完成之后,最后才入库追加到表中去。

(3) 发现某个表的记录太多,例如超过一千万条,则要对该表进行水平分割。水平分割的做法是,以该表主键PK的某个值为界线,将该表的记录水平分割为两个表。若发现某个表的字段太多,例如超过八十个,则垂直分割该表,将原来的一个表分解为两个表。

(4) 对数据库管理系统DBMS进行系统优化,即优化各种系统参数,如缓冲区个数。

(5) 在使用面向数据的SQL语言进行程序设计时,尽量采取优化算法。

总之,要提高数据库的运行效率,必须从数据库系统级优化、数据库设计级优化、程序实现级优化,这三个层次上同时下功夫。

从概念上讲,系统属性环境变量 都是名称与值之间的映射。两种机制都能用来将用户定义的信息传递给 Java 进程。环境变量产生更多的全局效应,因为它们不仅对Java 子进程可见,而且对于定义它们的进程的所有子进程都是可见的。在不同的操作系统上,它们的语义有细微的差别,比如,不区分大小写。因为这些原因,环境变量更可能有意料不到的副作用。最好在可能的地方使用系统属性。环境变量应该在需要全局效应的时候使用,或者在外部系统接口要求使用环境变量时使用(比如 PATH)。

代码如下:

//import java.util.*;
import java.util.Properties;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;

public class GetSysPropertiesAndEnv
{
 public static void main(String [] args)
 {
  //获取所有系统属性
   Properties prpt = System.getProperties();
   Enumeration enm = prpt.propertyNames();  //返回系统属性列表中所有键的枚举
   String key = "";
   System.out.println("当前系统属性如下:=========");
   while(enm.hasMoreElements())
  {
   key = (String) enm.nextElement();
   System.out.println(key+":"+System.getProperty(key,"undefined"));
  }

  //获取所有环境变量的设置
   Map map = System.getenv();       //返回系统环境变量的字符串映射视图。
   Set  set  = map.keySet();        //返回映射中包含的键的 set 视图
   System.out.println("当前环境变量如下:=========");
   Iterator itr = set.iterator();
   while(itr.hasNext())
  {
   key = (String) itr.next();
   System.out.println(key+":"+map.get(key));
  }
 }
}

其中个人认为比较重要的系统属性如下:

java.home:Java 安装目录 (比如D:\JavaStudio\jdk15\jre)
java.class.path:Java 类路径
java.vm.version:Java虚拟机版本号(比如:1.5.0-b64)
java.version:Java版本号(比如:1.5.0)

os.name:操作系统的名称(比如:Windows XP)
os.version:操作系统的版本(比如:Windows XP 的版本为5.1)

user.home:用户的主目录 (比如:C:\Documents and Settings\zhangsan)
user.name:当前用户名
user.country:当前用户所属国家
user.dir:用户的当前工作目录

比较重要的环境变量(Windows操作系统):

%COMPUTERNAME%     返回计算机的名称。
%COMSPEC%     返回命令行解释器可执行程序的准确路径。

%WINDIR%    返回操作系统目录的位置。
%OS%     返回操作系统的名称。Windows 2000 将操作系统显示为 Windows_NT。
%PATH%    指定可执行文件的搜索路径。

%USERDOMAIN%    返回包含用户帐户的域的名称。
%USERNAME%    返回当前登录的用户的名称。

考虑下面的简单代码,A中包含B,C,而B中又包含C:

class A
{
 private B b;
 private C c =new C("default value");
 public A()
 {
  b = new B(c);
 }
 //some geter/setter method…
 }

class B
{
 private C c;
 public B(C c)
 {
  this.c = c;
 }
 //some geter/setter method…
}

class C
{
 private String str ;
 public C(String str)
 {
  this.str = str;
 }
 //some geter/setter method…
}

下面有一个D,继承A:

class D extends A
{
 public D(String str)
 {
  super(); //有没有这句结果都一样,因为在子类的构造函数中会自动调用父类的构造函数,所以不必显式调用。
  this.setC(new C(str));
  //this.setB(new B(new C(str)));
 }
}

另外有一个单独的测试类TestInit:

public class TestInit
{
 public static void main(String[] args)
 {
  D d = new D("new value");
  System.out.println(d.getC().getStr());
  System.out.println(d.getB().getC().getStr());
 }
}

输出结果为:
new value
default value

如果我们把D改成这样:
class D extends A
{
 public D(String str)
 {
  super();
  //this.setC(new C(str));
  this.setB(new B(new C(str)));
 }
}

则输出结果为:
default value
new value

这就证实了java中类的初始化过程是这样的:

先父类再子类,先成员变量再构造函数。

Next »