在这里工作也有半年了,有得有失. 近来心里十分的茅盾, 项目已经黄色第5周了.我还是没有去改变它. 我不知道是自己不行, 还是自己不想. 学了不多的自我激励方法, 可是都不见效果. 也知道这个时候只有自己才能解救自己.
以下内容转载于
http://www.aspxboy.com/private/5294/default.aspx,感谢该作者的分享.
1. 如何设置一个From的边界
2. 如何建立一个透明的From
3. 如何设置窗体在屏幕中的位置
4. 如何使最小化和最大化按钮不可用
5. 如何使一个窗体不见
6. 如何设置使窗体成为非矩形的.
7. 如何使一个窗体在屏幕的最顶端.
8. 如何显示一个Model和非Model的窗体
9. 如何制作一个MDI的窗体
10. 如何将你的窗体不显示在任务条上.
11. 如何制作一个带启动屏幕的窗体.
12. 如何使你的窗体TrayIcon.
13. 如何修改控制窗体的尺寸和长宽尺寸.
14. 如何建立一个Windows Explorer风格的窗体.
15. 如何设置初始的启动窗体
16. 如何建立一个有背景图像的窗体
==========================================================================================
1. 如何设置一个From的边界
form总共有七种不同的边界风格让你设置,你可以在设计时刻也可以运行时通过代码动态的来设置它.这七种边界风格分别是:
none (System.Windows.Forms.FormBorderStyle.None )
fixed 3D (System.Windows.Forms.FormBorderStyle.Fixed3D)
fixed Dialog (System.Windows.Forms.FormBorderStyle.FixedDialog)
fixed Single(System.Windows.Forms.FormBorderStyle.FixedSingle)
fixed Tool Window(System.Windows.Forms.FormBorderStyle.FixedToolWindow)
sizable(system.windows.forms.formborderstyle.sizable)
sizable Tool Window
(system.windows.forms.formborderstyle.sizabletoolwindow)
在设计方式下在vs.net IDE的 Properties window中设置FormBorderStyle属性就可以了.
在运行方式下你可以用代码来完成:
dlgbx1.formborderstyle = System.Windows.Forms.FormBorderStyle.FixedDialog
这七种边界类型VB6中就有,没有什么大的变化,运行方式下你需要对照不同的枚举变量进行设置.
2. 如何建立一个透明的From
你可以通过两种方法在设计时刻和运行时刻来做到这一点.
设计时刻,你可以在vs.net IDE的 Properties window, 设置Opacity 属性达到这个效果.这个值从0.0到1.0 . 0表示完全透明,1.0表示完全不透明.
运行时刻你可以用下面的编码设置窗体的opactiy属性来做到.具体:
frmtransparentform.opacity = 0.76; ( C# )
看得出现在很简单了,你已经不用再去了解什么alpha变量了.透明始终只是一种效果,不要滥用它.
3. 如何设置窗体在屏幕中的位置
你可以设置窗体的startposition属性,vs.net一般给你一个保守的选项” WindowsDefaultLocation“ 这样系统在Load窗体时将根据用户当前的计算机设置来确定一个值,你也可以在设计时将它改成另一个值”Center”.
如果你一定要在设计方式下确定窗体在屏幕出现的位置你可以先设置startposition为manual,然后设置location的x和y的值.
运行时用代码实现似乎更简洁一些:
Form1.Location = new Point (100, 100) ( VB.NET )
当然你也可以分别修改的Location的X和Y值,对应的是窗体的Left和Top属性,比如:
form1.left += 200 ( VB.NET )
form1.top -= 100 ( VB.NET )
另外一个属性将也将影响窗体在屏幕的位置:desktoplocation 这个属性主要是在你设置窗体的位置相对于任务栏时非常实用(当你把任务条放在屏幕的顶或左边时,其实相应改动了desktop coordinates (0,0)),你可以这样设置这个不出现在设计属性窗口中的属性,
form1.desktoplocation = new Point (100,100)
窗体在屏幕中的位置将主要取决于各自用户具体的硬件和设置情况,所以保守的作法是用默认的” WindowsDefaultLocation”或 ”Center”;专业的作法是自己先获取系统的设置然后编码动态计算后进行设置,不然很容易在屏幕上找不到你的窗体.
4. 如何使最小化和最大化按钮不可用
在设置窗体的form.minimizebox和form.maximizebox 当为True时表示显示,False时表示不可.用编程方式见下:
frmmaxmin.minnimizebox = False ( VB.NET)
frmmaxmin.maxmnimizebox = True ( VB.NET )
5. 如何使一个窗体不见
我想最直接的办法是你调用 Hide()方法来做到这一点.不过我想提供另一种方法,看了之后你会获得一些其它的启发. ( VB.NET )
Private Const WS_EX_TOOLWINDOW As Int32 = &H80
Private Const WS_POPUP As Int32 = &H80000000
Private Const WS_VISIBLE As Int32 = &H10000000
Private Const WS_SYSMENU As Int32 = &H80000
Private Const WS_MAXIMIZEBOX As Int32 = &H10000
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As System.Windows.Forms.CreateParams
cp = MyBase.CreateParams
cp.ExStyle = WS_EX_TOOLWINDOW
cp.Style = WS_POPUP Or WS_VISIBLE Or WS_SYSMENU Or WS_MAXIMIZEBOX
cp.Height = 0
cp.Width = 0
Return cp
End Get
End Property
原来是把Height 和Width都设置成0 ,我想这种方式和Hide()调用的底层可能是不同的。
6. 如何设置使窗体成为非矩形的.
这个问题我想我提供的不是最专业的作法,至少它还不能达到我期望的那样,也就是说它在某些事件中它还会变回矩形.但至少我可以告诉你:如果试图调用原来的win32’s API SetWindowRng是不行的,我曾如此的尝试过.现在你可能需要知道有关窗体的Region属性
' // ( VB.NET )
Public Sub SetWindowRegion()
Dim FormPath As System.Drawing.Drawing2D.GraphicsPath
Dim Reg As Drawing.Region
Dim lRet As Long
FormPath = New Drawing2D.GraphicsPath()
FormPath.AddEllipse(New Rectangle(0, 0, 250, 120))
Me.Region = New Region(FormPath)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Me.Region = Nothing
SetWindowRegion()
End Sub
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
Me.Region = Nothing
SetWindowRegion()
End Sub
7. 如何使一个窗体在屏幕的最顶端.
这是很实用的一个功能,现在你不用在调用其它api了,只用设置topmost 属性为True就可以了.对于这个属性在设计时刻和运行时刻都是可以进行修改的.代码方式:
myTopForm.TopMost = True ( VB.NET)
8. 如何显示一个Model和非Model的窗体
model和modeless的窗体主要将取决于你的应用,最多的是用在显示对话框.当你需要model的窗体时你调用myform. ShowDialog而非Model的调用MyForm.Show,对于ShowDialog有一个可选参数ower可以让你为一个窗体建立父子关系.比如:
' Visual Basic
Private Sub mnuAbout_Click(…args…)
Dim f As New FormOption
f.ShowDialog Me
End Sub
有一点需要注意的是对于ShowDialog来说,当执行到这一句,窗体显示,但这之后的代码将不会执行,只到窗口关闭之后才继续执行,而对于Show来说是即时的,显示窗体之后将立即执行下面的代码.
9. 如何制作一个MDI的窗体
1. 建立一个新的Windows Application项目
2. 分别加入两个窗体Form1 、Form2
3. 设置Form1的IsMdiContainer属性为True。使它成为MDI主窗体。
4. 在Form2中加入一个RichTextBox控件,并设置Dock为:Fill
5. 在Tools 窗体中拖一个MainMenu到窗体Form1,然后建立一个菜单File|Windows|Help三个菜单项,File中包括New、Exit菜单项;Windows中包括Cascade、Horizontal等。
6. 设置Windows菜单项的MdiList属性=True, 这样每一个MDI子窗口将自动加在Windows菜单项下面。
7. 双击New菜单项,然后加入以下代码:
private void menuNew_Click(object sender, System.EventArgs e)
{
Form2 NewMdiChild ;
NewMdiChild = new Form2() ;
NewMdiChild.MdiParent = this ;
NewMdiChild.Show() ;
}
8. 在Windows的Cascade等菜单项中加入以下代码:
private void menuWindowCasca_Click(object sender, System.EventArgs e)
{
this.LayoutMdi( MdiLayout.Cascade) ;
}
另外还有以下常用的:
this.layoutmdi(mdilayout.tilehorizontal);
this.layoutmdi(mdilayout.tilevertical);
9. F5运行。
最终版的vs.net 不知是否会有一个通用的模板,不过用完全手工的方式产生一个MDI的窗口,显得有些繁琐,不如VS.NET的IDE方式下那么简洁。
10. 如何将你的窗体不显示在任务条上.
当窗体的边界风格是tools Window时它都不会出现在任务条上的.另外上面标题5中介绍的方法不仅窗体看不见,也不会出现在任务条上.
如果你现在在Dotnet的世界,这件事也变的简单,任何的Winform窗体现在都有ShowInTaskbar属性,所以你只要简单的设置这个属性就可以了。同样你可以选择在属性窗口中将ShowInTaskbar由True改为False。或是用代码的方式:
MyTaskBarFrm.ShowInTaskbar = false ; ( C# )
11. 如何制作一个带启动屏幕的窗体.
需要你准备两个winform的窗体,一个叫它:splashscreen,把它做成一个漂亮的窗体。然后你需要一个主窗体叫它:form1吧,然后在这个窗体加入下面的代码。
// ( C# )
protected override void OnLoad ( System.EventArgs e )
{
//make load take a long time
Thread.Sleep(2000);
base.OnLoad(e);
}
然后在main中加入这样的代码:
[STAThread]
static void Main()
{
SplashScreen splashForm = new SplashScreen();
splashForm.Show();
Form1 mainForm = new Form1() ;
mainForm.Load += new EventHandler(splashForm.MainScreen_Load);
Application.Run(mainForm);
}
不要忘了加上对threading的引用: using System.Threading;
12. 如何使你的窗体TrayIcon.
实现这个功能你可以运用notifyicon控件来达到,从tools Windows中将NotifyIcon拖到你的窗体上然后在下面的事件加入如下代码,F5。
' // VB.NET
Private mIconA As Icon = New Icon("Icon1.ico")
Private mIconB As Icon = New Icon("Icon2.ico")
Private mIconDisplayed As Boolean
Public Sub New()
MyBase.New
Form1 = Me
'This call is required by the Win Form Designer.
InitializeComponent
'TODO: Add any initialization after the InitializeComponent() call
'this form isn't used directly so hide it immediately
Me.Hide()
'setup the tray icon
Initializenotifyicon()
End Sub
Private Sub Initializenotifyicon()
'setup the default icon
notifyicon = New System.Windows.Forms.NotifyIcon()
NotifyIcon.Icon = mIconA
NotifyIcon.Text = "Right Click for the menu"
NotifyIcon.Visible = True
mIconDisplayed = True
'Insert all MenuItem objects into an array and add them to
'the context menu simultaneously
Dim mnuItms(3) As MenuItem
mnuItms(0) = New MenuItem("Show Form...", New EventHandler(AddressOf Me.ShowFormSelect))
mnuItms(0).DefaultItem = True
mnuItms(1) = New MenuItem("Toggle Image", New EventHandler(AddressOf Me.ToggleImageSelect))
mnuItms(2) = New MenuItem("-")
mnuItms(3) = New MenuItem("Exit", New EventHandler(AddressOf Me.ExitSelect))
Dim notifyiconMnu As ContextMenu = New ContextMenu(mnuItms)
notifyicon.ContextMenu = notifyiconMnu
End Sub
Public Sub ShowFormSelect(ByVal sender As Object, ByVal e As System.EventArgs)
'Display the settings dialog
Dim SettingsForm As New SettingsForm()
SettingsForm.ShowDialog()
End Sub
Public Sub ToggleImageSelect(ByVal sender As Object, ByVal e As System.EventArgs)
'called when the user selects the 'Toggle Image' context menu
'determine which icon is currently visible and switch it
If mIconDisplayed Then
'called when the user selects the 'Show Form' context menu
NotifyIcon.Icon = mIconB
NotifyIcon.Text = "Sad"
mIconDisplayed = False
Else
NotifyIcon.Icon = mIconA
NotifyIcon.Text = "Happy"
mIconDisplayed = True
End If
End Sub
Public Sub ExitSelect(ByVal sender As Object, ByVal e As System.EventArgs)
'called when the user selects the 'Exit' context menu
'hide the tray icon
NotifyIcon.Visible = False
'close up
Me.Close()
End Sub
'Form overrides dispose to clean up the component list.
Public Overloads Overrides Sub Dispose()
MyBase.Dispose()
components.Dispose()
End Sub
图标文件你自己准备了,如果成功你可以看到有关NotifyIcond的各种功能了。
13. 如何修改控制窗体的尺寸和长宽尺寸.
主要是修改winform的size, Width 和Height属性。同样它们都是可以在设计和运行时刻进行修改和设置。
form1.size = New System.Drawing.Size(100, 100) ( VB.NET )
form1.width += 100 (VB.NET )
form1.height -= 20 (VB.NET )
14. 如何建立一个Windows Explorer风格的窗体.
1.建立一个新的windows Application
2.从toolbox窗口拖一个treeview控件、、一个splitterk控件、一个listview控件,分别在属性窗口中设置treeview的dock属性为::left;设置listview控件的dock属性为:fill
3: F5 运行
15. 如何设置初始的启动窗体
无论是c#还是visual Basic的Winform项目中你都可以在Solution Explorer窗口中右键你的Project,然后选择属性,从你Project的属性页中选择你启动的窗体或是Main()方法。
有些不同的是在目前的vs.net Beta2中C#项目会自动产生Main() 方法,Visual Basic.Net 的项目中你必须自己添加Main()代码,C#中你可以将Form1改成任何你可以启动的窗体名:
// ( C# )
static void Main()
{
Application.Run(new Form1());
}
16. 如何建立一个有背景图像的窗体
现在的winform中所有的窗体都有一个backgroundimage属性,只用对它赋值就可以了。普通窗体可以在运行模式也可以在运行模式完成这个设置。比如在initializecomponent()或窗体的构造函数中加入这样的代码:
this.backgroundimage = new Bitmap("C:\\DotNetApp\\WinForm\\Tile.bmp" ) ;
对于MDI的主窗体要麻烦一些,在VS.NET的IDE窗体中,当你设置完IsMdiContainer属性为True后,你需要查看一下InitializeComponent()中是否有这样的代码 ( C# ):
this.mdiClient1.Dock = System.Windows.Forms.DockStyle.Fill;
this.mdiClient1.Name = "mdiClient1";
或是在窗口的属性窗口组合框中看到mdiclient1 System.Windows.Forms.mdiClient.这就是主MDI窗口,不过我没有在dotnet的文档中找到任何有关System.Windows.Forms.mdiClient的说明。然后你可以在InitializeComponent()或窗体的构造函数中加入这样的代码( C# ):
this.mdiclient1.backgroundimage = new Bitmap("C:\\DotNetApp\\WinForm\\Tile.bmp" ) ;
网上有一个ImageView的例子,里面演示了给MDI主窗体中背景上加入一行Logo文字的方法,这样使你的MDI窗体看起来很商业化,具体的你可以这样做:
1. 先在VS.NET 自动产生代码的InitializeComponent中看是否有这样的语句( C# ):
this.controls.addrange(new System.Windows.Forms.Control[] {this.mdiClient1});
又是这个mdiClient (haha)
2. 建立以下两个函数用于显示这个Logo字符:
// ( C# )
protected void Mdi_OnPaint ( Object s, System.Windows.Forms.PaintEventArgs e )
{
Control c = (Control)s;
Rectangle r1 = c.ClientRectangle;
r1.Width -= 4;
r1.Height -= 4;
Rectangle r2 = r1;
r2.Width -= 1;
r2.Height -= 1;
Font f = new Font("Tahoma", 8);
String str = "MyWinform.NET ?2001 MyWinform Application V1.0";
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Far;
sf.LineAlignment = StringAlignment.Far;
e.Graphics.DrawString(str, f, new SolidBrush(SystemColors.ControlDarkDark), r1, sf);
e.Graphics.DrawString(str, f, new SolidBrush(SystemColors.ControlLight), r2, sf);
}
protected void Mdi_OnResize ( Object s , System.EventArgs e )
{
Control c = (Control)s;
c.Invalidate();
}
3. 在InitializeComponent()或窗体的构造函数中加入这样的代码:
( C# )
this.Controls[0].Paint += new PaintEventHandler( Mdi_OnPaint ) ;
this.Controls[0].Resize += new EventHandler( Mdi_OnResize ) ;
注意将它加在InitializeComponent()后面或是在InitializeComponent函数中this.Controls.AddRange函数之后。
昨天下班是计算机已经关机了。可今天早上一开到启动Windows时系统一片蓝屏。我用安全模式也进入不了。后来把硬盘拆下来,安装到同事的机子上进行硬盘检查。如果分区,坏道等。结果没有什么问题,但为了资料的安全,我把有用的资料都copy到他机子上。把硬盘重新安装回我的机子上。结果怎么样。。。
神了一点问题也没有。真是虚惊一场呀。
我用记事本打开一个以前的分页程序。把其中的一部份代码copy到我的现在的程序中,可是编译器提示illegal character \12288错误。我按它提示的错误找到发生错误的行。我用别的变量名试了一下是可以的。难道是这个变量名输入时用了中文的输入法。我check一下,可是还是没有解决。我又重新声明了一个与这个变量名一样的变量,把原来的注释起来。后来发现可以了,我再把现在的注释掉,用原来的变量,还是不行。我把它删除掉重新写了一遍包括空格也删除。OK,就可以了。我想可能还是有中文的输入字符或是空格。
以面的问题可真是不是问题的问题,如果遇到同样的问题的朋友看看是否也是犯了同样的错。
最后发现是一个中文的空格,我在删除该变量时发现有一个空格的距离较大。
因我的机子内存才512M要运行JBuilder2006,还要运行oracle9i时速度很慢,所以我先把oracle的几个服务关了。后来我要使用oracle是一直连接不上,提示“没有TNS监听”。我一查看服务,果然那个oracleOraHome90TNSListener没有启动,我一接点击启动,可还是提示那句没有TNS监听。这是为什么呢?lt;br />第一种可能是否把计算机名改了。如果是就按下面的步骤做?lt;br />把安装目录下的listener.ora打开察看。如:d:\oracle\ora90\network\admin\listener.ora.
打开该配置文件后发现如下一段配置信息:
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = local)(PORT = 1521))
)
)
)
看到这一行HOST=local这个是计算机名字,这个名字要与现在的计算机名对应。如果不知道自己的计算机名是什么可以到“我的电脑”的属性中有一个“网络标识”的tab?你在完整的计算机名称后面看到的就是你的计算机名了?lt;br />以下内容转载http://www3.ccw.com.cn/club/essence/200202/8252.htm版权归原作?
近来,浏览BBS时,常看到“急急急!如何启动OMS?”的字眼,就针对以上这类问题,我有些经验想和大家共同分享?lt;br />能否正常启动OEM或OMS关键有以下两点:
第一.Oracle的系统服务是否开启;
第二.登录时用的用户名和口令是否正确?lt;br />
那么先针对第一点谈谈Oracle的系统服务。在完全安装的情况下,Oracle的系统服务共?1项:
1.Oracle OLAP 9.0.1.0.1
2.Oracle OLAP Agent
3.OracleOraHome90Agent
4.OracleOraHome90ClientCache
5.OracleOraHome90HTTPServer
6.OracleOraHome90ManagementServer(0.5M)
7.OracleOraHome90PagingServer
8.OracleOraHome90SNMPPeerEncapsulator
9.OracleOraHome90SNMPPeerMasterAgent
10.OracleOraHome90TNSListener(5.2M)
11.OracleServiceORACLE(70M)
(注:OraHome90是可以在安装时改变的Oracle的主目录名称,是安装时的默认?
其中最重要的服务有3个,分别是OracleOraHome90ManagementServer、OracleOraHome90TNSListener?lt;br />OracleServiceORACLE。下面就来看一下有哪些启动错误与它们有关?lt;br />
1.Oracle系统提示:Ora-12541:TNS:没有监听器;
2.操作系统提示:在本地计算机无法启动OMS服务
错误?053:服务并未及时响应来控制请求附带?lt;br /> 以上两种错误提示大都是由OracleOraHome90TNSListener监听服务引起的?lt;br />解决方法:控制面?>管理工具->服务->右键单击“OracleOraHome90TNSListener”,再单击“启动”?lt;br />
3.Oracle系统提示:Ora-12500:TNS:监听程序无法启动专用服务器进程;
该错误是由OracleServiceORACLE专用服务器进程引起的?lt;br />解决方法:控制面?>管理工具->服务->右键单击“OracleServiceORACLE”,再单击“启动”?lt;br />
4.Oracle系统提示:VTK-1000:无法连接到Management Server?lt;br /> 请验证您已输入Oracle Management Server的正确主机名和状态?lt;br /> 该错误引起的原因有两种,一是OracleOraHome90ManagementServer还没启动;二是没有输入主机名?lt;br />解决方法:控制面?>管理工具->服务->右键单击“OracleOraHome90ManagementServer”,再单击“启动?
或是输入您这台计算机的完整名称?lt;br />小结:这三个服务的启动或关闭还有先后的顺序。一般来讲,启动时必须先启动OracleOraHome90TNSListener启动OracleOraHome90ManagementServer或OracleServiceORACLE,在启动OracleOraHome90ManagementServer时,同时也启动了OracleServiceORACLE。而关闭时必须先关闭OracleOraHome90ManagementServer再关闭OracleOraHome90TNSListener或OracleServiceORACLE,关闭OracleOraHome90ManagementServer时,若有提示输入用户名和口令,请输入sysman的用户名和口令,以确保成功的执行。有些其他提示如:资源已被占用,I/O重复,端口已被使用等等之类的话,那最好与系统管理员联系,再寻求解决办法?lt;br />
type
Status report
message
/zz3in1/SrvTest
description
The requested resource (/zz3in1/SrvTest) is not available.
这是为什呢?
用过了../../SrvTest 这个是不行的。././SrvTest这样可以。还有./SrvTest也可以。
用document.getElementById("01").innerHTML/innerText都可以。如:<tr><td id="01">Hello</td></tr>要把Hello取出来就可以用document.getElementById("01").innerHTML/innerText。
但是用innerHTML与用innerText有什么区别吗?用innerHTML会把这个标记中的所有HTML标记与值取出来。innerText只会取最后的值。
如果你在安装oracle8i时,系统会自己给你安装一个JDK1.1的或1.2的。然后你安装JDK1.5后,在系统环境中设置了JAVA_HOME是JDK1.5的,path中也设置了javaroot\JDK1.5\bin可是你怎么样也不能用JDK1.5中的命令。C:\Documents and Settings\Administrator>java
Registry key 'Software\JavaSoft\Java Runtime Environment\CurrentVersion'
has value '1.1', but '1.2' is required.
改注册表HKEY_LOCAL_MACHINE 中的SOFTWARE--JavaSoft--Java Runtime Environment--CurrentVersion的值改成了1.5
系统会提示你:C:\Documents and Settings\Administrator>java
Registry key 'Software\JavaSoft\Java Runtime Environment\CurrentVersion'
has value '1.5', but '1.2' is required.这是为什么呢?因你的系统中安装了旧的版本JDK,而且有程序程序有使用到它。这时你只要在当前的用户系统环境下设置一个JAVA_HOME(可以不要)并且在系统环境的path的最前面加上javaroot\jdk1.5\bin。这样就OK了。你可以把DOS窗口关闭再开启。WINDOWS2K不要重启计算机。WINDOWS98的要重启。
以下信息是转载http://www.aaunion.net/cn/blog/more.asp?name=magicmao&id=687
document
文挡对象 - JavaScript脚本语言描述
---------------------------------------------------------------------
注:页面上元素name属性和JavaScript引用的名称必须一致包括大小写
否则会提示你一个错误信息 "引用的元素为空或者不是对象"
---------------------------------------------------------------------
对象属性
document.title //
设置文档标题等价于HTML的<title>标签
document.bgColor //
设置页面背景色
document.fgColor //
设置前景色(文本颜色)
document.linkColor //
未点击过的链接颜色
document.alinkColor //
激活链接(焦点在此链接上)的颜色
document.vlinkColor //
已点击过的链接颜色
document.URL //
设置URL属性从而在同一窗口打开另一网页
document.fileCreatedDate //
文件建立日期,只读属性
document.fileModifiedDate //
文件修改日期,只读属性
document.fileSize //
文件大小,只读属性
document.cookie //
设置和读出cookie
document.charset //
设置字符集 简体中文:gb2312
---------------------------------------------------------------------
对象方法
document.write() //
动态向页面写入内容
document.createElement(Tag) //
创建一个html标签对象
document.getElementById(ID) //
获得指定ID值的对象
document.getElementsByName(Name) //
获得指定Name值的对象
---------------------------------------------------------------------
images
集合(页面中的图象)
a)
通过集合引用
document.images //
对应页面上的<img>标签
document.images.length //
对应页面上<img>标签的个数
document.images[0] //
第1个<img>标签
document.images[i] //
第i-1个<img>标签
b)
通过nane属性直接引用
<img name="oImage">
document.images.oImage //document.images.name
属性
c)
引用图片的src属性
document.images.oImage.src //document.images.name
属性.src
d)
创建一个图象
var oImage
oImage = new Image()
document.images.oImage.src="/1.jpg"
//
同时在页面上建立一个<img>标签与之对应就可以显示
<html>
<img name=oImage>
<script language="javascript">
var oImage
oImage = new Image()
document.images.oImage.src="/1.jpg"
</script>
</html>
----------------------------------------------------------------------
forms
集合(页面中的表单)
a)
通过集合引用
document.forms //
对应页面上的<form>标签
document.forms.length //
对应页面上<form>标签的个数
document.forms[0] //
第1个<form>标签
document.forms[i] //
第i-1个<form>标签
document.forms[i].length //
第i-1个<form>中的控件数
document.forms[i].elements[j] //
第i-1个<form>中第j-1个控件
b)
通过标签name属性直接引用
<form name="Myform"><input name="myctrl"></form>
document.Myform.myctrl //document.
表单名.控件名
-----------------------------------------------------------------------
<html>
<!--Text
控件相关Script-->
<form name="Myform">
<input type="text" name="oText">
<input type="password" name="oPswd">
<form>
<script language="javascript">
//
获取文本密码框的值
document.write(document.Myform.oText.value)
document.write(document.Myform.oPswd.value)
</script>
</html>
-----------------------------------------------------------------------
<html>
<!--Select
控件相关Script-->
<form name="Myform">
<select name="oSelect">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</form>
<script language="javascript">
//
遍历select控件的option项
var length
length=document.Myform.oSelect.length
for(i=0;i<length;i++)
document.write(document.Myform.oSelect[i].value)
</script>
<script language="javascript">
//
遍历option项并且判断某个option是否被选中
for(i=0;i<document.Myform.oSelect.length;i++){
if(document.Myform.oSelect[i].selected!=true)
document.write(document.Myform.oSelect[i].value)
else
document.write("<font color=red>"+document.Myform.oSelect[i].value+"</font>")
}
</script>
<script language="javascript">
//
根据SelectedIndex打印出选中的option
//(0
到document.Myform.oSelect.length-1)
i=document.Myform.oSelect.selectedIndex
document.write(document.Myform.oSelect[i].value)
</script>
<script language="javascript">
//
动态增加select控件的option项
var oOption = document.createElement("OPTION");
oOption.text="4";
oOption.value="4";
document.Myform.oSelect.add(oOption);
</script>
<html>
-----------------------------------------------------------------------
<Div id="oDiv">Text</Div>
document.all.oDiv //
引用图层oDiv
document.all.oDiv.style
document.all.oDiv.style.display="" //
图层设置为可视
document.all.oDiv.style.display="none" //
图层设置为隐藏
/*document.all
表示document中所有对象的集合
只有ie支持此属性,因此也用来判断浏览器的种类*/
-----------------------------------------------------------------------
我写了一个测试oracle8.1的连接程序。用thin的方式连接。URL:jdbc:oracle:thin:@127.0.0.1:1521:orc;这个URL是正确的。我在thin与@中间少写一个冒号。这是一个很低级的错误,以后要小心呀。
如果下面的连接有出现class没有找到的异常,有可能是没有加裁到驱动程序,还有一种是驱动不对。
1、Oracle8/8i/9i数据库(thin模式)
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
String url="jdbc:oracle:thin:@localhost:1521:rcl"; //orcl为数据库的SID
String user="test";
String password="test";
Connection conn= DriverManager.getConnection(url,user,password);
2、DB2数据库
Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
String url="jdbc:db2://localhost:5000/sample"; //sample为你的数据库名
String user="admin";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);
3、Sql Server7.0/2000数据库
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
String url="jdbc:microsoft:sqlserver://lin56:1433;DatabaseName=pubs";
//mydb为数据库
String user="sa";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);
4、Sybase数据库
Class.forName("com.sybase.jdbc.SybDriver").newInstance();
String url =" jdbcybase:Tds:localhost:5007/myDB";//myDB为你的数据库名
Properties sysProps = System.getProperties();
SysProps.put("user","userid");
SysProps.put("password","user_password");
Connection conn= DriverManager.getConnection(url, SysProps);
5、Informix数据库
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
user=testuser;password=testpassword"; //myDB为数据库名
Connection conn= DriverManager.getConnection(url);
6、MySQL数据库
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
//myDB为数据库名
Connection conn= DriverManager.getConnection(url);
7、PostgreSQL数据库
Class.forName("org.postgresql.Driver").newInstance();
String url ="jdbcostgresql://localhost/myDB" //myDB为数据库名
String user="myuser";
String password="mypassword";
Connection conn= DriverManager.getConnection(url,user,password);
8、access数据库直连用ODBC的
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
String url="jdbcdbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
Connection conn = DriverManager.getConnection(url,"","");
Statement stmtNew=conn.createStatement() ;
二、JDBC连接MySql方式
下面是使用JDBC连接MySql的一个小的教程
1、查找驱动程序
MySQL目前提供的java驱动程序为Connection/J,可以从MySQL官方网站下载,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驱动程序为纯java驱动程序,不需做其他配置。
2、动态指定classpath
如果需要执行时动态指定classpath,就在执行时采用-cp方式。否则将上面的.jar文件加入到classpath环境变量中。
3、加载驱动程序
try{
Class.forName(com.mysql.jdbc.Driver);
System.out.println(Success loading Mysql Driver!);
}catch(Exception e)
{
System.out.println(Error loading Mysql Driver!);
e.printStackTrace();
}
4、设置连接的url
jdbc:mysql://localhost/databasename[?pa=va][&pa=va]
三、以下列出了在使用JDBC来连接Oracle数据库时可以使用的一些技巧
1、在客户端软件开发中使用Thin驱动程序
在开发Java软件方面,Oracle的数据库提供了四种类型的驱动程序,二种用于应用软件、applets、servlets等客户端软件,另外二种用于数据库中的Java存储过程等服务器端软件。在客户机端软件的开发中,我们可以选择OCI驱动程序或Thin驱动程序。OCI驱动程序利用Java本地化接口(JNI),通过Oracle客户端软件与数据库进行通讯。Thin驱动程序是纯Java驱动程序,它直接与数据库进行通讯。为了获得最高的性能,Oracle建议在客户端软件的开发中使用OCI驱动程序,这似乎是正确的。但我建议使用Thin驱动程序,因为通过多次测试发现,在通常情况下, Thin驱动程序的性能都超过了OCI驱动程序。
2、关闭自动提交功能,提高系统性能
在第一次建立与数据库的连接时,在缺省情况下,连接是在自动提交模式下的。为了获得更好的性能,可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能,如下所示:
conn.setAutoCommit(false);
值得注意的是,一旦关闭了自动提交功能,我们就需要通过调用Connection类的commit()和rollback()方法来人工的方式对事务进行管理。
3、在动态SQL或有时间限制的命令中使用Statement对象
在执行SQL命令时,我们有二种选择:可以使用PreparedStatement对象,也可以使用Statement对象。无论多少次地使用同一个 SQL命令,PreparedStatement都只对它解析和编译一次。当使用Statement对象时,每次执行一个SQL命令时,都会对它进行解析和编译。这可能会使你认为,使用PreparedStatement对象比使用Statement对象的速度更快。然而,我进行的测试表明,在客户端软件中,情况并非如此。因此,在有时间限制的SQL操作中,除非成批地处理SQL命令,我们应当考虑使用Statement对象。
此外,使用Statement对象也使得编写动态SQL命令更加简单,因为我们可以将字符串连接在一起,建立一个有效的SQL命令。因此,我认为,Statement对象可以使动态SQL命令的创建和执行变得更加简单。
4、利用helper函数对动态SQL命令进行格式化
在创建使用Statement对象执行的动态SQL命令时,我们需要处理一些格式化方面的问题。例如,如果我们想创建一个将名字O'Reilly插入表中的SQL命令,则必须使用二个相连的“''”号替换O'Reilly中的“'”号。完成这些工作的最好的方法是创建一个完成替换操作的helper方法,然后在连接字符串心服用公式表达一个SQL命令时,使用创建的helper方法。与此类似的是,我们可以让helper方法接受一个Date型的值,然后让它输出基于Oracle的to_date()函数的字符串表达式。
5、利用PreparedStatement对象提高数据库的总体效率
在使用PreparedStatement对象执行SQL命令时,命令被数据库进行解析和编译,然后被放到命令缓冲区。然后,每当执行同一个 PreparedStatement对象时,它就会被再解析一次,但不会被再次编译。在缓冲区中可以发现预编译的命令,并且可以重新使用。在有大量用户的企业级应用软件中,经常会重复执行相同的SQL命令,使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能。如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务,我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。
6、在成批处理重复的插入或更新操作中使用PreparedStatement对象
如果成批地处理插入和更新操作,就能够显著地减少它们所需要的时间。Oracle提供的Statement和 CallableStatement并不真正地支持批处理,只有PreparedStatement对象才真正地支持批处理。我们可以使用 addBatch()和executeBatch()方法选择标准的JDBC批处理,或者通过利用PreparedStatement对象的 setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制,可以以如下所示的方式调用setExecuteBatch():
PreparedStatement pstmt3D null;
try {
((OraclePreparedStatement)pstmt).setExecuteBatch(30);
...
pstmt.executeUpdate();
}
调用setExecuteBatch()时指定的值是一个上限,当达到该值时,就会自动地引发SQL命令执行,标准的executeUpdate()方法就会被作为批处理送到数据库中。我们可以通过调用PreparedStatement类的sendBatch()方法随时传输批处理任务。
7、使用Oracle locator方法插入、更新大对象(LOB)
Oracle的PreparedStatement类不完全支持BLOB和CLOB等大对象的处理,尤其是Thin驱动程序不支持利用 PreparedStatement对象的setObject()和setBinaryStream()方法设置BLOB的值,也不支持利用 setCharacterStream()方法设置CLOB的值。只有locator本身中的方法才能够从数据库中获取LOB类型的值。可以使用 PreparedStatement对象插入或更新LOB,但需要使用locator才能获取LOB的值。由于存在这二个问题,因此,我建议使用 locator的方法来插入、更新或获取LOB的值。
8、使用SQL92语法调用存储过程
在调用存储过程时,我们可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并没有什么实际的好处,而且会给以后维护你的应用程序的开发人员带来麻烦,因此,我建议在调用存储过程时使用SQL92。
9、使用Object SQL将对象模式转移到数据库中
既然可以将Oracle的数据库作为一种面向对象的数据库来使用,就可以考虑将应用程序中的面向对象模式转到数据库中。目前的方法是创建Java bean作为伪装的数据库对象,将它们的属性映射到关系表中,然后在这些bean中添加方法。尽管这样作在Java中没有什么问题,但由于操作都是在数据库之外进行的,因此其他访问数据库的应用软件无法利用对象模式。如果利用Oracle的面向对象的技术,可以通过创建一个新的数据库对象类型在数据库中模仿其数据和操作,然后使用JPublisher等工具生成自己的Java bean类。如果使用这种方式,不但Java应用程序可以使用应用软件的对象模式,其他需要共享你的应用中的数据和操作的应用软件也可以使用应用软件中的对象模式。
10、利用SQL完成数据库内的操作
我要向大家介绍的最重要的经验是充分利用SQL的面向集合的方法来解决数据库处理需求,而不是使用Java等过程化的编程语言。
如果编程人员要在一个表中查找许多行,结果中的每个行都会查找其他表中的数据,最后,编程人员创建了独立的UPDATE命令来成批地更新第一个表中的数据。与此类似的任务可以通过在set子句中使用多列子查询而在一个UPDATE命令中完成。当能够在单一的SQL命令中完成任务,何必要让数据在网上流来流去的?我建议用户认真学习如何最大限度地发挥SQL的功能。
ORACLE 数据库备份技术
ORACLE数据库是一种大型关系型的数据库,可以存贮达到存贮TB的数据,那么如何保证这些数据的安全尤其至关重要,我们从1991年开始使用 ORACLE数据库,通过这些年的使用,我们制定了一整套的ORACLE数据库的备份制度。现在把我们的备份制度介绍给大家,供大家参考。
1.根据实际需要决定数据库的运行方式
ORACLE数据库有两种运行方式:一是归档方式(ARCHIVELOG),归档方式的目的是当数据库发生故障时最大限度恢复所有已提交的事物;二是不归档方式(NOARCHIVELOG),恢复数据库到最近的回收点。我们根据数据库的高可用性和用户可承受丢失的工作量的多少,把我们正式运行的数据库采用为归档方式;那些正在开发和调试的数据库采用不归档方式。
2如何改变数据库的运行方式
2.1在创建数据库时设置数据库的运行的方式
在创建数据库时,作为创建数据库的一部分,就决定了数据库初始的存档方式。一般情况下为NOARCHIVELOG方式。当数据库创建好以后,根据我们的需要把需要运行在归档方式的数据库改成ARCHIVELOG方式。
2.2改变不归档方式为为归档方式
关闭数据库,备份已有的数据
改变数据库的运行方式是对数据库的重要改动,所以要对数据库做备份,对可能出现的问题作出保护。
启动Instance ,Mount数据库但不打开数据库,来改变归档方式
sqldba lmode=y(svrmgrl)
sqldba>connect internal
sqldba>startup mount
sqldba>alter database archivelog;
使能自动存档
在初始化文件init*.ora(一般放ORACLE根目录的下层目录dbs下)加参数:
log_archive_start=true
指定存档的重做登录文件名和存放的位置
同样是在初始化文件init*.ora中加入下面的参数:
log_archive_format=%S.arc
log_archive_dest=/arch12/arch (arch12 是日志文件存放的目录)
关闭数据库,重新启动数据库,归档方式转换完成。
3回收制度
3.1根据数据库的运行方式和可承受丢失的工作量来决定数据库的回收制度对于不归档方式,我们用的是ORACLE数据库的逻辑备份Export ,回收的制度是:一个月作一次全备份(x01.dmp),一周作一次累积备份(c*.dmp),一天一次增量备份(I*.dmp),具体的是星期一到星期五作增量备份,星期六做累积备份或全备份,每次做完备份后自动传到其它的机器上存储。这些备份都是自动执行的,后面给出程序文本。
对于归档方式,我们用的是ORCALE的物理备份:当数据库创建好以后,做一次物理上的全备份,平时在不关闭数据库的前提下,一个星期对经常改变的数据文件做联机的数据库数据文件的物理备份;当数据库的结构发生改变,如:增加表空间,加数据文件等,如允许关机,正常关闭数据库,重新做数据库全备份,否则,备份控制文件,备份数据文件照常。联机的日志文件我们是写在阵列上的,不用镜象和备份。
3.2回收的方法
3.2.1不归档方式
我们拿曙光AIX操作系统为例,来讲解以下如何做自动备份:
---- a.首先建UNIX用户 demo/demo
---- b.拷贝oracle用户下的 .profile 到 demo 用户下,以保证 demo 用户可以用 Export命令
---- c.用root用户登录,编辑 /var/adm/cron/cron.allow 加入用户名demo,这样demo用户就有权自动执行数据库备份的shell程序;
---- d.创建数据库备份程序,放到本用户的下层目录bin下,并且这些文件要有可执行权文件zlbf1:(增量备份1,星期一执行的程序)
. /u11/demo/.profile
exp system/manager inctype=INCREMENTAL file=i01.dmp
ftp -n< < !
open 10.10.10.40
user demo demo
binary
prompt
cd backup40
put i01.dmp
close
bye
!
文件zlbf2:(增量备份2, 星期二执行的程序)
. /u11/demo/.profile
exp system/manager inctype=INCREMENTAL file=i02.dmp
ftp -n< < !
open 10.10.10.40
user demo demo
binary
prompt
cd backup40
put i02.dmp
close
bye
!
文件zlbf3:(增量备份3, 星期三执行的程序)
. /u11/demo/.profile
exp system/manager inctype=INCREMENTAL file=i03.dmp
ftp -n< < !
open 10.10.10.40
user demo demo
binary
prompt
cd backup40
put i03.dmp
close
bye
!
文件zlbf4:(增量备份4, 星期四执行的程序)
. /u11/demo/.profile
exp system/manager inctype=INCREMENTAL file=i04.dmp
ftp -n< < !
open 10.10.10.40
user demo demo
binary
prompt
cd backup40
put i04.dmp
close
bye
!
文件zlbf5:(增量备份5, 星期五执行的程序)
. /u11/demo/.profile
exp system/manager inctype=INCREMENTAL file=i05.dmp
ftp -n< < !
open 10.10.10.40
user demo demo
binary
prompt
cd backup40
put i05.dmp
close
bye
!
文件zlbf6:(增量备份6, 星期六执行的程序)
. /u11/demo/.profile
js=`ls c*.dmp|wc -l`
if test = 0
then
exp system/manager inctype=CUMULATIVE file=c01.dmp
ftp -n< < !
open 10.10.10.40
user demo demo
binary
prompt
cd backup40
put c01.dmp
close
bye
!
fi
if test = 1
then
exp system/manger inctype=CUMULATIVE file=c02.dmp
ftp -n< < !
open 10.10.10.40
user demo demo
binary
prompt
cd backup40
put c02.dmp
close
bye
!
fi
if test = 2
then
exp system/maneger inctype=CUMULATIVE file=c03.dmp
ftp -n< < !
open 10.10.10.40
user demo demo
binary
prompt
cd backup40
put c03.dmp
close
bye
!
fi
if test = 3
then
exp system/manager inctype=COMPLETE file=x01.dmp
ftp -n< < !
open 10.10.10.40
user demo demo
binary
prompt
cd backup40
put x01.dmp
close
bye
!
rm c*.dmp
fi
---- e.在demo 用户下建一个文件,假如叫:cron.demo,文件内容如下
59 22 * * 1 bin/zlbf1
59 22 * * 2 bin/zlbf2
59 22 * * 3 bin/zlbf3
59 22 * * 4 bin/zlbf4
59 22 * * 5 bin/zlbf5
59 22 * * 6 bin/zlbf6
---- f.在demo用户下执行下面的命令:
crontab cron.demo 执行的结果放到
/var/spool/cron/crontabs/demo文件里
---- g.重新启动cron 进程,命令:kill -1 进程号
---- h.执行结果放在本用户的邮件里
---- i.查看结果是否执行,请看:/var/adm/cron/log文件
3.2.2归档方式
---- a. 找到要回收的数据文件、联机重做登录文件、控制文件和参数文件
---- b. 正常关闭数据库,作一次全回收(用操作系统的TAR命令,可以写成shell程序),然后打开数据库供正常使用,shell程序如下:
tar cvf /dev/rmt/ctape2 /u1/oracle/dbs/ctrl1ora7.ctl
/u1/oracle/dbs/ctrl2ora7.ctl
/u1/oracle/dbs/ctrl3ora7.ctl
/u1/oracle/dbs/systora7.dbf
/u1/oracle/dbs/rbsora7.dbf
/u1/oracle/dbs/tempora7.dbf
/u1/oracle/dbs/toolora7.dbf
/u1/oracle/dbs/usrora7.dbf
/ls1/ls1.dbf
/u1/oracle/dbs/log1ora7.dbf
/u1/oracle/dbs/log2ora7.dbf
/u1/oracle/dbs/log3ora7.dbf
---- c. 经常作联机的表空间和数据文件的部分回收
首先标记联机表空间回收的开始
alter tablespace 表空间名 begin backup;
用操作系统命令备份数据文件
最后标记联机的表空间回收结束
alter tablespace 表空间名 end backup
---- 多个表空间可以一起做标记,备份做标记的所有数据文件后,一起标记结束。
---- d. 当数据库结构发生改变后,要对它的控制文件做回收
sqldba >alter database backup
controlfile to ’文件名’ reuse;
数据库设计中的14个技巧
1. 原始单据与实体之间的关系
可以是一对一、一对多、多对多的关系。在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体。在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单证对应多个实体,或多张原始单证对应一个实体。这里的实体可以理解为基本表。明确这种对应关系后,对我们设计录入界面大有好处。
〖例1〗:一份员工履历资料,在人力资源信息系统中,就对应三个基本表:员工基本情况表、社会关系表、工作简历表。这就是“一张原始单证对应多个实体”的典型例子。
2. 主键与外键
一般而言,一个实体不能既无主键又无外键。在E—R 图中, 处于叶子部位的实体, 可以定义主键,也可以不定义主键(因为它无子孙), 但必须要有外键(因为它有父亲)。
主键与外键的设计,在全局数据库的设计中,占有重要地位。当全局数据库的设计完成以后,有个美国数据库设计专家说:“键,到处都是键,除了键之外,什么也没有”,这就是他的数据库设计经验之谈,也反映了他对信息系统核心(数据模型)的高度抽象思想。因为:主键是实体的高度抽象,主键与外键的配对,表示实体之间的连接。
3. 基本表的性质
基本表与中间表、临时表不同,因为它具有如下四个特性:
(1) 原子性。基本表中的字段是不可再分解的。
(2) 原始性。基本表中的记录是原始数据(基础数据)的记录。
(3) 演绎性。由基本表与代码表中的数据,可以派生出所有的输出数据。
(4) 稳定性。基本表的结构是相对稳定的,表中的记录是要长期保存的。
理解基本表的性质后,在设计数据库时,就能将基本表与中间表、临时表区分开来。
4. 范式标准
基本表及其字段之间的关系, 应尽量满足第三范式。但是,满足第三范式的数据库设计,往往不是最好的设计。为了提高数据库的运行效率,常常需要降低范式标准:适当增加冗余,达到以空间换时间的目的。
〖例2〗:有一张存放商品的基本表,如表1所示。“金额”这个字段的存在,表明该表的设计不满足第三范式,因为“金额”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。但是,增加“金额”这个冗余字段,可以提高查询统计的速度,这就是以空间换时间的作法。
在Rose 2002中,规定列有两种类型:数据列和计算列。“金额”这样的列被称为“计算列”,而“单价”和“数量”这样的列被称为“数据列”。
表1 商品表的表结构
商品名称商品型号单价数量金额
电视机 29吋 2,500 40 100,000
5. 通俗地理解三个范式
通俗地理解三个范式,对于数据库设计大有好处。在数据库设计中,为了更好地应用三个范式,就必须通俗地理解三个范式(通俗地理解是够用的理解,并不是最科学最准确的理解):
第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;
第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;
第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。
没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。具体做法是:在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余。
6. 要善于识别与正确处理多对多的关系
若两个实体之间存在多对多的关系,则应消除这种关系。消除的办法是,在两者之间增加第三个实体。这样,原来一个多对多的关系,现在变为两个一对多的关系。要将原来两个实体的属性合理地分配到三个实体中去。这里的第三个实体,实质上是一个较复杂的关系,它对应一张基本表。一般来讲,数据库设计工具不能识别多对多的关系,但能处理多对多的关系。
〖例3〗:在“图书馆信息系统”中,“图书”是一个实体,“读者”也是一个实体。这两个实体之间的关系,是一个典型的多对多关系:一本图书在不同时间可以被多个读者借阅,一个读者又可以借多本图书。为此,要在二者之间增加第三个实体,该实体取名为“借还书”,它的属性为:借还时间、借还标志(0表示借书,1表示还书),另外,它还应该有两个外键(“图书”的主键,“读者”的主键),使它能与“图书”和 “读者”连接。
7. 主键PK的取值方法
PK是供程序员使用的表间连接工具,可以是一无物理意义的数字串, 由程序自动加1来实现。也可以是有物理意义的字段名或字段名的组合。不过前者比后者好。当PK是字段名的组合时,建议字段的个数不要太多,多了不但索引占用空间大,而且速度也慢。
8. 正确认识数据冗余
主键与外键在多表中的重复出现, 不属于数据冗余,这个概念必须清楚,事实上有许多人还不清楚。非键字段的重复出现, 才是数据冗余!而且是一种低级冗余,即重复性的冗余。高级冗余不是字段的重复出现,而是字段的派生出现。
〖例4〗:商品中的“单价、数量、金额”三个字段,“金额”就是由“单价”乘以“数量”派生出来的,它就是冗余,而且是一种高级冗余。冗余的目的是为了提高处理速度。只有低级冗余才会增加数据的不一致性,因为同一数据,可能从不同时间、地点、角色上多次录入。因此,我们提倡高级冗余(派生性冗余),反对低级冗余(重复性冗余)。
9. E--R图没有标准答案
信息系统的E--R图没有标准答案,因为它的设计与画法不是惟一的,只要它覆盖了系统需求的业务范围和功能内容,就是可行的。反之要修改E--R图。尽管它没有惟一的标准答案,并不意味着可以随意设计。好的E—R图的标准是:结构清晰、关联简洁、实体个数适中、属性分配合理、没有低级冗余。
10. 视图技术在数据库设计中很有用
与基本表、代码表、中间表不同,视图是一种虚表,它依赖数据源的实表而存在。视图是供程序员使用数据库的一个窗口,是基表数据综合的一种形式, 是数据处理的一种方法,是用户数据保密的一种手段。为了进行复杂处理、提高运算速度和节省存储空间, 视图的定义深度一般不得超过三层。若三层视图仍不够用, 则应在视图上定义临时表, 在临时表上再定义视图。这样反复交迭定义, 视图的深度就不受限制了。
对于某些与国家政治、经济、技术、军事和安全利益有关的信息系统,视图的作用更加重要。这些系统的基本表完成物理设计之后,立即在基本表上建立第一层视图,这层视图的个数和结构,与基本表的个数和结构是完全相同。并且规定,所有的程序员,一律只准在视图上操作。只有数据库管理员,带着多个人员共同掌握的“安全钥匙”,才能直接在基本表上操作。请读者想想:这是为什么?
11. 中间表、报表和临时表
中间表是存放统计数据的表,它是为数据仓库、输出报表或查询结果而设计的,有时它没有主键与外键(数据仓库除外)。临时表是程序员个人设计的,存放临时记录,为个人所用。基表和中间表由DBA维护,临时表由程序员自己用程序自动维护。
12. 完整性约束表现在三个方面
域的完整性:用Check来实现约束,在数据库设计工具中,对字段的取值范围进行定义时,有一个Check按钮,通过它定义字段的值城。
参照完整性:用PK、FK、表级触发器来实现。
用户定义完整性:它是一些业务规则,用存储过程和触发器来实现。
13. 防止数据库设计打补丁的方法是“三少原则”
(1) 一个数据库中表的个数越少越好。只有表的个数少了,才能说明系统的E--R图少而精,去掉了重复的多余的实体,形成了对客观世界的高度抽象,进行了系统的数据集成,防止了打补丁式的设计;
(2) 一个表中组合主键的字段个数越少越好。因为主键的作用,一是建主键索引,二是做为子表的外键,所以组合主键的字段个数少了,不仅节省了运行时间,而且节省了索引存储空间;
(3) 一个表中的字段个数越少越好。只有字段的个数少了,才能说明在系统中不存在数据重复,且很少有数据冗余,更重要的是督促读者学会“列变行”,这样就防止了将子表中的字段拉入到主表中去,在主表中留下许多空余的字段。所谓“列变行”,就是将主表中的一部分内容拉出去,另外单独建一个子表。这个方法很简单,有的人就是不习惯、不采纳、不执行。
数据库设计的实用原则是:在数据冗余和处理速度之间找到合适的平衡点。“三少”是一个整体概念,综合观点,不能孤立某一个原则。该原则是相对的,不是绝对的。“三多”原则肯定是错误的。试想:若覆盖系统同样的功能,一百个实体(共一千个属性) 的E--R图,肯定比二百个实体(共二千个属性) 的E--R图,要好得多。
提倡“三少”原则,是叫读者学会利用数据库设计技术进行系统的数据集成。数据集成的步骤是将文件系统集成为应用数据库,将应用数据库集成为主题数据库,将主题数据库集成为全局综合数据库。集成的程度越高,数据共享性就越强,信息孤岛现象就越少,整个企业信息系统的全局E—R图中实体的个数、主键的个数、属性的个数就会越少。
提倡“三少”原则的目的,是防止读者利用打补丁技术,不断地对数据库进行增删改,使企业数据库变成了随意设计数据库表的“垃圾堆”,或数据库表的“大杂院”,最后造成数据库中的基本表、代码表、中间表、临时表杂乱无章,不计其数,导致企事业单位的信息系统无法维护而瘫痪。
“三多”原则任何人都可以做到,该原则是“打补丁方法”设计数据库的歪理学说。“三少”原则是少而精的原则,它要求有较高的数据库设计技巧与艺术,不是任何人都能做到的,因为该原则是杜绝用“打补丁方法”设计数据库的理论依据。
14. 提高数据库运行效率的办法
在给定的系统硬件和系统软件条件下,提高数据库系统的运行效率的办法是:
(1) 在数据库物理设计时,降低范式,增加冗余, 少用触发器, 多用存储过程。
(2) 当计算非常复杂、而且记录条数非常巨大时(例如一千万条),复杂计算要先在数据库外面,以文件系统方式用C++语言计算处理完成之后,最后才入库追加到表中去。这是电信计费系统设计的经验。
(3) 发现某个表的记录太多,例如超过一千万条,则要对该表进行水平分割。水平分割的做法是,以该表主键PK的某个值为界线,将该表的记录水平分割为两个表。若发现某个表的字段太多,例如超过八十个,则垂直分割该表,将原来的一个表分解为两个表。
(4) 对数据库管理系统DBMS进行系统优化,即优化各种系统参数,如缓冲区个数。
(5) 在使用面向数据的SQL语言进行程序设计时,尽量采取优化算法。
总之,要提高数据库的运行效率,必须从数据库系统级优化、数据库设计级优化、程序实现级优化,这三个层次上同时下功夫。
上述十四个技巧,是许多人在大量的数据库分析与设计实践中,逐步总结出来的。对于这些经验的运用,读者不能生帮硬套,死记硬背,而要消化理解,实事求是,灵活掌握。并逐步做到:在应用中发展,在发展中应用。
特别声明以上内容是转至http://dev2dev.bea.com.cn/bbsdoc/20060112181.html,如果您认为该文档的内容侵犯了您的权益,请与整理者(excelarthur.com.cn)联系,与Dev2Dev网站无关。
在安装完了JBuilder9时,打开JB9会弹出一个对话框讲你要注册。这时你没有注册号时,有一个叫JB9_Ent_KeyGen.exe的文件,这时你只要将这个文件copy to 你安装的目录下。double click this file,这时你只要点击"Generate",再点击"Save"就OK了。例如:E:\JBuilder9\jdk1.4\bin下放入copy的文件。这个文件一定要放入jdk1.4\bin下面。
如果你做过很多java程序,你可能对java集合类很熟悉,例如Vector和ArrayList。你可以创建一个集合并向其中增加元素:
-
- List lst = new ArrayList();
-
- lst.add(new Integer(37));
在这个特殊的范例中,一个整型值37用于构造一个Integer封装类对象,然后那个对象被加入到列表。
这个简单的范例展示集合的一个基础-他们用于操纵一列对象,其中的每个对象是一个类或者接口类型。因此,一个ArrayList可以包含Object,String,Float以及Runnable类型的对象。集合类不能用于原始数据类型的列表,例如整型数组。
如果你在你的程序中使用原始类型的数组,你如何操纵它们呢?这个技巧就给你展示几个你可以使用的技术。
第一个技术是排序。java.util.Arrays类包含一套排序和查找数组的类方法,例如:
-
- import java.util.Arrays;
-
- public class ArrayDemo1 {
- public static void main(String args[]) {
- int vec[] = {37, 47, 23, -5, 19, 56};
- Arrays.sort(vec);
- for (int i = 0; i < vec.length; i++) {
- System.out.println(vec[i]);
- }
- }
- }
这个演示程序初始化一个整数数组然后调用Arrays.sort升序排序那个数组。
类似的,你可以在排完序的数组上进行二分法查找:
-
- import java.util.Arrays;
-
- public class ArrayDemo2 {
- public static void main(String args[]) {
- int vec[] = {-5, 19, 23, 37, 47, 56};
- int slot = Arrays.binarySearch(vec, 35);
- slot = -(slot + 1);
- System.out.println("insertion point = " + slot);
- }
- }
这个程序有个微妙的概念,如果二分法查找失败它将返回:
-(insertion point) - 1
这个演示程序以参数35调用查找方法,而那个参数在数组中不存在,方法返回值-4,如果这个值加一再取其负数就得到3,这就是35应该被插入到数组中的位置,换言之,值-5, 19和23在数组中占据的位置是0,1和2。因此值35应该在索引3的位置,而37, 47以及56顺延。搜索方法并不进行实际的插入操作而只是指出应该在何处插入。
除了排序和查找,我们还可以对原始类型数组做什么?另一个有用的技术是将一个原始数组转换为等价的对象类型数组。每个对应元素使用它们的封装器类,例如在封装数组中,37成为Integer(37)。
-
- import java.util.Arrays;
- import java.lang.reflect.Array;
-
- public class ArrayDemo3 {
-
- // if input is a single-dimension primitive array,
- // return a new array consisting of wrapped elements,
- // else just return input argument
-
- public static Object toArray(Object vec) {
-
- // if null, return
-
- if (vec == null) {
- return vec;
- }
-
- // if not an array or elements not primitive, return
-
- Class cls = vec.getClass();
- if (!cls.isArray()) {
- return vec;
- }
- if (!cls.getComponentType().isPrimitive()) {
- return vec;
- }
-
- // get array length and create Object output array
-
- int length = Array.getLength(vec);
- Object newvec[] = new Object[length];
-
- // wrap and copy elements
-
- for (int i = 0; i < length; i++) {
- newvec[i] = Array.get(vec, i);
- }
-
- return newvec;
- }
-
- public static void main(String args[]) {
-
- // create a primitive array
-
- int vec[] = new int[]{1, 2, 3};
-
- // wrap it
-
- Object wrappedvec[] = (Object[])toArray(vec);
-
- // display result
-
- for (int i = 0; i < wrappedvec.length; i++) {
- System.out.println(wrappedvec[i]);
- }
- }
- }
方法"toArray"的参数是一个Object对象(数组可以被赋值给一个Object引用)。如果参数是null或者代表的不是原始类型数组那么这个方法简单的返回参数值。java.lang.Class工具类用于判断参数是否是一个数组并获取数组的底层元素的类型。
一旦做完这些检查,使用java.lang.reflect.Array工具类的反射工具方法就可以获取原始数组的长度并获得数组的单个元素。Array.get获得的每个元素被返回到封装器类中,例如Integer或者Double。
最终的范例基于前面的那个并向你展示如何在数组上使用集合特性。这假设你已经有一个对象数组。
-
- import java.util.Arrays;
- import java.util.List;
-
- public class ArrayDemo4 {
- public static void main(String args[]) {
- Object vec[] = {new Integer(37), new Integer(47)};
- List lst = Arrays.asList(vec);
- lst.set(1, new Integer(57));
- for (int i = 0; i < vec.length; i++) {
- System.out.println(vec[i]);
- }
- }
- }
在这个程序中,vec是一个对象数组,包含Integer(37)和Integer(47),然后Arrays.asList被调用。它返回一个集合(List接口类型),使用数组作为集合的后台存储。换言之,ArrayList这样的集合类型在它内部有某种存储类型去存储集合元素。在这个例子中,使用的存储类型是作为参数传递到Arrays.asList的数组。这意味着集合方法所做的改变会被反射到底层的数组。
修改集合中的元素1导致底层的数组也改变,程序的输出是:
37
57
因此如果你有一个对象数组,你可以在它上面使用集合特性,数组自身作为底层存储。
我们也可以将集合转换为一个对象数组,例如:
Object vec[] = lst.toArray();
package com.cucu.test;
/**
* @author http://www.linewell.com <a href=mailto:cg@linewell.com>cg@linewell.com</a>
* @version 1.0
*/
public class Sort {
public void swap(int a[], int i, int j) {
int tmp = a;
a = a[j];
a[j] = tmp;
}
public int partition(int a[], int low, int high) {
int pivot, p_pos, i;
p_pos = low;
pivot = a[p_pos];
for (i = low + 1; i <= high; i++) {
if (a > pivot) {
p_pos++;
swap(a, p_pos, i);
}
}
swap(a, low, p_pos);
return p_pos;
}
public void quicksort(int a[], int low, int high) {
int pivot;
if (low < high) {
pivot = partition(a, low, high);
quicksort(a, low, pivot - 1);
quicksort(a, pivot + 1, high);
}
}
public static void main(String args[]) {
int vec[] = new int[] { 37, 47, 23, -5, 19, 56 };
int temp;
//选择排序法(Selection Sort)
long begin = System.currentTimeMillis();
for (int k = 0; k < 1000000; k++) {
for (int i = 0; i < vec.length; i++) {
for (int j = i; j < vec.length; j++) {
if (vec[j] > vec) {
temp = vec;
vec = vec[j];
vec[j] = temp;
}
}
}
}
long end = System.currentTimeMillis();
System.out.println("选择法用时为:" + (end - begin));
//打印排序好的结果
for (int i = 0; i < vec.length; i++) {
System.out.println(vec);
}
// 冒泡排序法(Bubble Sort)
begin = System.currentTimeMillis();
for (int k = 0; k < 1000000; k++) {
for (int i = 0; i < vec.length; i++) {
for (int j = i; j < vec.length - 1; j++) {
if (vec[j + 1] > vec[j]) {
temp = vec[j + 1];
vec[j + 1] = vec[j];
vec[j] = temp;
}
}
}
}
end = System.currentTimeMillis();
System.out.println("冒泡法用时为:" + (end - begin));
//打印排序好的结果
for (int i = 0; i < vec.length; i++) {
System.out.println(vec);
}
//插入排序法(Insertion Sort)
begin = System.currentTimeMillis();
for (int k = 0; k < 1000000; k++) {
for (int i = 1; i < vec.length; i++) {
int j = i;
while (vec[j - 1] < vec) {
vec[j] = vec[j - 1];
j--;
if (j <= 0) {
break;
}
}
vec[j] = vec;
}
}
end = System.currentTimeMillis();
System.out.println("插入法用时为:" + (end - begin));
//打印排序好的结果
for (int i = 0; i < vec.length; i++) {
System.out.println(vec);
}
//快速排序法(Quick Sort)
Sort s = new Sort();
begin = System.currentTimeMillis();
for (int k = 0; k < 1000000; k++) {
s.quicksort(vec, 0, 5);
}
end = System.currentTimeMillis();
System.out.println("快速法用时为:" + (end - begin));
//打印排序好的结果
for (int i = 0; i < vec.length; i++) {
System.out.println(vec);
}
}
}
以下是运行结果:
选择法用时为:234
56
47
37
23
19
-5
冒泡法用时为:172
56
47
37
23
19
-5
插入法用时为:78
56
47
37
23
19
-5
快速法用时为:297
56
47
37
23
19
-5*