Java防SQL注入,最简单的办法是杜绝SQL拼接,SQL注入攻击能得逞是因为在原有SQL语句中加入了新的逻辑,如果使用PreparedStatement来代替Statement来执行SQL语句,其后只是输入参数,SQL注入攻击手段将无效,这是因为PreparedStatement不允许在不同的插入时间改变查询的逻辑结构,大部分的SQL注入已经挡住了,在WEB层我们可以过滤用户的输入来防止SQL注入比如用Filter来过滤全局的表单参数。
import java.io.IOException; import java.util.Iterator; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 通过Filter过滤器来防SQL注入攻击 * */ public class SQLFilter implements Filter { private String inj_str = "'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|; |or|-|+|,"; protected FilterConfig filterConfig = null; /** * Should a character encoding specified by the client be ignored? */ protected boolean ignore = true; public void init(FilterConfig config) throws ServletException { this.filterConfig = config; this.inj_str = filterConfig.getInitParameter("keywords"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)request; HttpServletResponse res = (HttpServletResponse)response; Iterator values = req.getParameterMap().values().iterator();//获取所有的表单参数 while(values.hasNext()){ String[] value = (String[])values.next(); for(int i = 0;i < value.length;i++){ if(sql_inj(value[i])){ //TODO这里发现sql注入代码的业务逻辑代码 return; } } } chain.doFilter(request, response); } public boolean sql_inj(String str) { String[] inj_stra=inj_str.split("\\|"); for (int i=0 ; i < inj_stra.length ; i++ ) { if (str.indexOf(" "+inj_stra[i]+" ")>=0) { return true; } } return false; } } |
也可以单独在需要防范SQL注入的JavaBean的字段上过滤:
/** * 防止sql注入 * * @param sql * @return */ public static String TransactSQLInjection(String sql) { return sql.replaceAll(".*([';]+|(--)+).*", " "); } |
在Java中有两类线程:用户线程(UserThread)、守护线程(DaemonThread)。
所谓守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。
用户线程和守护线程两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。
将线程转换为守护线程可以通过调用Thread对象的setDaemon(true)方法来实现。在使用守护线程时需要注意一下几点:
(1)thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。
(2)在Daemon线程中产生的新线程也是Daemon的。
(3)守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。
代码示例:
- import java.util.concurrent.TimeUnit;
- /**
- * 守护线程
- */
- public class Daemons {
- /**
- * @param args
- * @throws InterruptedException
- */
- public static void main(String[] args) throws InterruptedException {
- Thread d = new Thread(new Daemon());
- d.setDaemon(true); //必须在启动线程前调用
- d.start();
- System.out.println("d.isDaemon() = " + d.isDaemon() + ".");
- TimeUnit.SECONDS.sleep(1);
- }
- }
- class DaemonSpawn implements Runnable {
- public void run() {
- while (true) {
- Thread.yield();
- }
- }
- }
- class Daemon implements Runnable {
- private Thread[] t = new Thread[10];
- public void run() {
- for (int i=0; i<t.length; i++) {
- t[i] = new Thread(new DaemonSpawn());
- t[i].start();
- System.out.println("DaemonSpawn " + i + " started.");
- }
- for (int i=0; i<t.length; i++) {
- System.out.println("t[" + i + "].isDaemon() = " +
- t[i].isDaemon() + ".");
- }
- while (true) {
- Thread.yield();
- }
- }
- }
|
运行结果:
- d.isDaemon() = true.
- DaemonSpawn 0 started.
- DaemonSpawn 1 started.
- DaemonSpawn 2 started.
- DaemonSpawn 3 started.
- DaemonSpawn 4 started.
- DaemonSpawn 5 started.
- DaemonSpawn 6 started.
- DaemonSpawn 7 started.
- DaemonSpawn 8 started.
- DaemonSpawn 9 started.
- t[0].isDaemon() = true.
- t[1].isDaemon() = true.
- t[2].isDaemon() = true.
- t[3].isDaemon() = true.
- t[4].isDaemon() = true.
- t[5].isDaemon() = true.
- t[6].isDaemon() = true.
- t[7].isDaemon() = true.
- t[8].isDaemon() = true.
- t[9].isDaemon() = true.
|
以上结果说明了守护线程中产生的新线程也是守护线程。
如果将mian函数中的TimeUnit.SECONDS.sleep(1);注释掉,运行结果如下:
- d.isDaemon() = true.
- DaemonSpawn 0 started.
- DaemonSpawn 1 started.
- DaemonSpawn 2 started.
- DaemonSpawn 3 started.
- DaemonSpawn 4 started.
- DaemonSpawn 5 started.
- DaemonSpawn 6 started.
- DaemonSpawn 7 started.
- DaemonSpawn 8 started.
- DaemonSpawn 9 started.
|
以上结果说明了如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。下面的例子也说明了这个问题。
代码示例:
- import java.util.concurrent.TimeUnit;
- /**
- * Finally shoud be always run ?
- */
- public class DaemonsDontRunFinally {
- /**
- * @param args
- */
- public static void main(String[] args) {
- Thread t = new Thread(new ADaemon());
- t.setDaemon(true);
- t.start();
- }
- }
- class ADaemon implements Runnable {
- public void run() {
- try {
- System.out.println("start ADaemon...");
- TimeUnit.SECONDS.sleep(1);
- } catch (InterruptedException e) {
- System.out.println("Exiting via InterruptedException");
- } finally {
- System.out.println("This shoud be always run ?");
- }
- }
- }
|
运行结果:
start ADaemon...
如果将main函数中的t.setDaemon(true);注释掉,运行结果如下:
start ADaemon...
This shoud be always run ?
前两篇文章中已经介绍了三种搭建Linux学习环境的方法,本文将介绍第四、第五种方法。
第四种方法:在Windows系统中,用VNC工具软件登录到远程服务器上的 Linux桌面。这种远程登录的方式,一方面可以用于远程配置和维护Linux服务器,另一方面也可以用它来在真实的环境中学习各种Linux命令。 VNC(Virtual Network Computing,虚拟网络计算机)软件主要由两部分组成,VNC server和VNC viewer。用户要先将VNC server安装在被控端的计算机上才能在主控端执行VNC viewer控制被控端。
VNC server与VNC viewer支持多种操作系统,如Unix、Linux、Solaris、Windows和MacOS,因此可将VNC server 及VNC viewer分别安装在不同的操作系统中进行控制。如果目前操作的主控端计算机没有安装VNC viewer,也可以通过一般的网页浏览器来控制被控端。VNC的主要工作原理是在服务器端运行 VNC server服务,然后在客户端就可以远程连接服务器端的桌面了。下面就介绍,在主控端的计算机操作系统为Win 7,被控端服务器的操作系统为64位RedHat Enterprise Linux 5.3上的VNC viewer与VNC server的安装与配置步骤:
1、在服务器端的RedHat中安装VNC server,安装包的文件名为“vnc-4.1.2-14.el5.x86_64.rpm”,此文件在光盘中的路径为“RedHat Enterprise Linux 5.3 for 64-bit AMD64 AND INTEL 64_Installation\Server”。
也可以打开网站http://rpm.pbone.net/,在如下所示的对话框中输入“vnc-4.1.2-14.el5”,然后点击SEARCH,也可以找到相应的RPM安装包,下载下来即可,如图9所示。
图9 下载RPM包网站图示
2、安装VNC server的rpm包。可以把安装包“vnc-4.1.2-14.el5.x86_64.rpm”拷贝到\root\.vnc目录下,然后在此目录下直接运行安装命令即可,安装过程的显示提示如下所示:
[root@localhost .vnc]# rpm -ivh vnc-4.1.2-14.el5.x86_64.rpm
warning: vnc-4.1.2-14.el5.x86_64.rpm: Header V3 DSA signature: NOKEY, key ID 37017186
Preparing... ########################################### [100%]
package vnc-4.1.2-14.el5.x86_64 is already installed
3、编辑.vnc目录下的xstartup文件。可以使用vi编辑器进行编辑,命令为“[root@localhost .vnc]#vi xstartup”,打开xstartup文件后在键盘上点击“A”字母键,使VI编辑器进入编辑状态。然后屏蔽掉最后一行,即在最后一行的前面加上符号 “#”,变成“#twm &”,然后再在最下面加上“gnome-session &”。完成后,点击“Esc”键,再点击“:”键,然后输入“wq”回车,即保存退出。加上“gnome-session &”是为了能够在Windows系统上显示Linxu的桌面,否则只能看到一个“终端”的命令行窗口。
4、设置登录用户。如果上面的安装成功,在目录/etc/sysconfig/下会有一个vncservers文件。用VI编辑器编辑vncservers文件,在最后加上VNCSERVERS="1:root",保存后退出。
5、设置VNC远程登录密码。运行命令“[root@localhost ~]# vncpasswd”,然后按提示设置好远程登录的密码。然后执行命令“[root@localhost ~]#vncserver”,会有如下显示:
New 'localhost.localdomain:1 (root)' desktop is localhost.localdomain:1
Starting applications specified in /root/.vnc/xstartup
Log file is /root/.vnc/localhost.localdomain:1.log
这里需要注意的是,上面的输出“localhost.localdomain:1 (root)”,说明在用浏览器远程登录Linux系统时,在浏览器地址栏中要输入的地址为“Linux服务器的IP地址:5801”,如果上面的输出为 “2(root)”,则在浏览器地址栏中要输入的命令就为“5802”。如果连接成功,输入密码后就可以远程控制Linux桌面了。
图10 用VNC Viewer软件登录的界面图示
6、用浏览器登录Linux桌面的画质可能不太好,可以在Windows下安装VNC Viewer工具软件直接连接。首先要在Windows系统中安装RealVNC软件,如“vnc-4.1.3-x86_win32.exe”。安装完成后,打开“开始”菜单里的RealVNC ---> VNC Viewer 4 ---> Run VNC Viewer,在VNC Viewer的地址栏中输入“Linux服务器的IP地址:1”,如果上面的输出为“2”,则在VNC Viewer的地址栏中的IP地址后面把“:1”换成“:2”,如图10所示,点击“OK”,然后输入在上面“5”中设置的密码,就可成功连接到远程 Linux桌面,犹如在本地操作Linux系统一样,如图11所示。
图11 用VNC Viewer远程登录到Linux桌面图示
若在VNC Viewer的“Server”地址栏中输入的IP地址后面所接的端口号,不是“localhost.localdomain:1 (root)”中的“1”,而是写成了其它的数字,那可能只能进入到Linux系统的终端命令行模式,而进入不到图形化的桌面模式。
下面将介绍第五种:用SSH方式登录到远程服务器的Linux系统中。其实和SSH登录方式非常相像的还有Telnet登录,但因为Telnet登录的用户名和密码,以及在配置管理当中所使用的Linux命令,都是以明文方式传送,没有任何安全措施,所以目前它基本上已经被SSH的登录方式所取代。SSH服务在Linux下的设置非常简单。下面就简要地介绍下SSH服务的设置与登录的步骤:
1、SSH服务的安装状态。此服务默认是安装的,但也可以通过以下命令来查询在Linux系统中是否安装了SSH服务。
[root@localhost ~]# rpm -qa | grep ssh
openssh-clients-4.3p2-29.el5
openssh-4.3p2-29.el5
openssh-askpass-4.3p2-29.el5
openssh-server-4.3p2-29.el5
若出现以上的显示结果,则表示此Linux系统已经安装了SSH服务。输出内容的第一行显示的是SSH的客户端软件包;第二行显示的是SSH的核心文件;第三行表示SSH支持对话框的显示,是一个基于X系统的密码诊断工具;第四行是SSH的服务器软件包。
2、SSH服务的运行状态。此服务默认也是自动运行的,但也可以通过以下命令来查询SSH服务的运行状态。
[root@localhost ~]#service sshd status
openssh-daemon (pid 5340) is running...
若出现以上的显示结果,则表示此Linux系统的SSH服务已经运行。其中,“sshd”是SSH服务的守护进程名称。若SSH服务没有启动的话,则运行命令[root@localhost ~]#service sshd restart即可。
图12 用SecureCRT以SSH方式登录的参数设置
3、用SSH进行远程登录的设置。若是在Windows系统中,没有自带的SSH客户端,可以在网上下载支持SSH远程登录的图形化工具软件,常用的有 SecureCRT、Putty等。如图12所示,是用SecureCRT进行远程SSH登录的设置。在“Hostname”中输入SSH服务器的IP地址,“Port”中输入22,“Username”中输入用户名。然后根据提示,输入密码,就可以连接到远程的SSH服务器。若是在Linux系统中进行远程的SSH登录,就可以在Linux的终端窗口的命令提示符下,直接使用命令#ssh 192.168.1.2进行远程登录即可。
4、SSH的配置文件。SSH有两个主要的配置文件,一个为客户端的配置文件ssh_config,一个为服务器端的配置文件sshd_config。这两个配置文件都位于目录/etc/ssh下。用VI编辑器就可以对这两个配置文件进行详细的配置和修改,以便用户在使用SSH时能满足一些特殊的要求。
总结
以上五种搭建Linux学习环境的模式,主要是根据实际情况,选择最适合自己的,它们之间无好坏之分。通常Linux高手对Linux的架构、命令都很熟悉,更习惯使用SSH的方式。这种方式在配置和管理服务器时更灵活,功能更强大。而对于网速带宽有保证的地方,同时又有充足的硬件服务器资源的话,采用第一种模式是最好的。
第二种和第三种模式主要适用有个人固定的笔记本或台式机电脑,但网络带宽却不能保证的用户。这时,在个人电脑或虚拟机上安装Linux,也是不错的选择。第四种和第一种有相似之处,都要求网络带宽要有保证,但第四种没有第一种使用起来更方便。第四种还必须在电脑上安装RealVNC软件才行,若不安装的话使用浏览器和JAVA程序控制远程的Linux,效果并不是很好。
相关链接:
五种方法教你搭建Linux学习环境(一)
五种方法教你搭建Linux学习环境(二)
问:SQL Server的警报问题应该如何解决?
答:具体的解决方法请参考下文 :
◆ 检查你是否使用了最新的Sql Server service pack。因为在最新的Sql Server service pack中已经修补了很多Sql Server使用警告(Alerts)的漏洞。应该确保在你的系统中已经安装了最新的Sql Server service pack补丁包。
◆ 检查SqlServerAgent服务的帐户是否作为成员运行在域用户群组(Domain User Group)下。LocalSystem帐户没有访问网络的权限,所以,如果你需要将事件记录在其他运行有Windows NT或Windows 2000机器上的应用程序日志上,或者你的作业(jobs)需要跨网络的资源,或者你需要通过e-mail或者pagers通知操作者,这时候,你就需要将SalServerAgent服务的帐户设置在域用户群组(Domain User Group)下作为它的成员。
◆ 如果所定义的警报都没有触发,检查SqlServerAgent和EventLog服务是否都在运行。如果你需要让你定义的警报被触发,这些服务必须被开启。所以,如果这些服务没有被运行的话,请运行它们。
◆ 如果有某个警报没有被触发,请确保它们是否被启用。警报可以被启用或禁用,为了检查一个警报是否被启用,你应该做以下这些步骤:
1、运行Sql Server Enterprise Manager
2、请打开服务器群组,然后打开某个服务器
3、请打开管理(Management),然后再打开Sql Server Agent
4、双击合适的警报以查看这个警报是否被启用了
5、检查警报的历史值以确定警报最后工作的日期和时间
为了检查一个警报的历史值,你应该做以下这些事情:
1、运行Sql Server Enterprise Manager
2、请打开服务器群组,然后打开某个服务器
3、请打开管理(Management),然后再打开Sql Server Agent
4、双击合适的警报以查看警报的历史值
5、核对每20秒维护的计数器值
因为Sql Server Agent每20秒间隔维护一个性能计数器,如果发现这个性能计数器只有几秒钟(少于20秒)才维护一次,那么极有可能你的这个警报将不会被触发。
6、检查Sql Server错误日志、Sql Server Agent错误日志以及Windows NT和Windows 2000的应用程序日志,以获得有关错误描述的更多详细信息。仔细检查核对当产生警报失败事件时,被记录在Sql Server错误日志、Sql Server Agent错误日志以及Windows NT和Windows 2000的应用程序日志中的日期和时间以及对错误的描述能帮助你分析产生警报失败事件的原因。
7、假如警报被触发了,但是这时候操作员却没有收到任何通知,请尝试手动使用“e-mail”,“pager”或者用“net send”将信息发送给操作员。在很多情况下,可能你输入了一个错%C。
工作以来,代码越写越多,程序也越来越臃肿,效率越来越低,对于我这样一个追求完美的程序员来说,这是绝对不被允许的,于是除了不断优化程序结构外,内存优化和性能调优就成了我惯用的“伎俩”。
要对Java程序进行内存优化和性能调优,不了解虚拟机的内部原理(或者叫规范更严谨一点)是肯定不行的,这里推荐一本好书《深入Java虚拟机(第二版)》(Bill Venners著,曹晓刚 蒋靖 译,实际上本文正是作者阅读本书之后,对Java虚拟机的个人理解阐述)。当然了,了解Java虚拟机的好处并不仅限于上述两点好处。从更深一点的技术层面上看,了解Java虚拟机的规范和实现,将更加有助于我们编写高效、稳定的Java代码。比如,假如了解Java虚拟机的内存模型,了解虚拟机的内存回收机制,那么我们就不会过分依赖它,而会在需要的时候显式的"释放内存"(Java代码不能显式释放内存,但是可以通过释放对象引用告知垃圾回收器回收该对象需要被回收),以降低不必要的内存消耗;假如我们了解Java栈的工作原理,那么我们就可以通过减少递归层数,减少循环次数来降低堆栈溢出的风险。可能对于应用开发人员来说,可能不会直接去涉及这些Java虚拟机底层实现的工作,但是了解这些背景知识,或多或少,都会对我们写的程序产生潜移默化的好的影响。
本篇文章,将简明扼要的说明Java虚拟机的体系结构和内存模型,如有用词不妥或解释不准确之处,请不吝指正,深感荣幸!
Java 虚拟机体系结构
类装载子系统
Java虚拟机有两种类装载器,分别是启动类装载器和用户自定义装载器。
通类装载子系统通过类的全限定名(包名和类名,网络装载还包括 URL)将 Class 装载进运行时数据区。对于每一个被装载的类型,Java虚拟机都会创建一个java.lang.Class类的实例来代表该类型,该实例被放在内存中的堆区,而装载的类型信息则位于方法区,这一点和所有其他对象都是一样的。
类装载子系统在装载一个类型前,除了要定位和导入对应的二进制class文件外,还要验证导入类的正确性,为类变量分配并初始化内存,以及解析符号引用为直接引用,这些动作严格按照以下顺序进行:
1)装载——查找并装载类型的二进制数据;
2)连接——执行验证,准备以及解析(可选)
3)验证 确保被导入类型的正确性
4)准备 为类变量分配内存,并将其初始化为默认值
5)解析 把类型中的符号引用转换为直接应用
方法区
对于每一个被类装载子系统装载的类型,虚拟机都会保存下列数据到方法区:
◆ 类型的全限定名
◆ 类型超类的全限定名(java.lang.Object没有超类)
◆ 类型是类类型还是接口类型
◆ 类型的访问修饰符
◆ 任何直接超接口的全限定名有序列表
除了上述基本类型信息,还将保存如下信息:
◆ 类型的常量池
◆ 字段信息(包括字段名、字段类型、字段修饰符)
◆ 方法信息(包括方法名、返回类型、参数的数量和类型、方法修饰符,如果方法不是抽象和本地的,还将保存方法的字节码、操作数栈和该方法栈帧中的局部变量区的大小和异常表)
◆ 常量以外的所有类变量(其实就是类的静态变量,因为静态变量是所有实例共享的,且与类型直接相关,所以他们是类一级的变量,作为类的成员被保存在方法区)
一个到类ClassLoader的引用
//返回的就是刚才保存的ClassLoader引用 String.class.getClassLoader(); |
一个到Class类的引用
//将返回刚才保存的Class类的引用 String.class; |
注意,方法区也是可以被垃圾回收器回收的。
堆
Java程序在运行时创建的所有类实例或数组都放在同一个堆中,而每一个Java虚拟机也是有一个对空间,所有线程共享一个堆(这就是一个多线程的Java程序会产生对象访问的同步问题的原因了)。
由于每一种Java虚拟机都有对虚拟机规范的不同实现,所以我们可能不知道每一种Java虚拟机在堆中是以何种形式表示对象实例的,不过我们可以通过下面这可能的实现来一窥端倪:
程序计数器
对于运行中的Java程序而言,每一个线程都有自己的PC(程序计数器)寄存器,它是在该线程启动时创建的,大小为一个字长,用来保存需要被执行的下一行代码的位置。
Java栈
每一个线程都有一个Java栈,以栈帧为单位保存线程的运行状态。虚拟机对Java栈的操作有两种:压栈和出栈,二者都已帧为单位。栈帧保存了传入参数、局部变量、中间运算结果等数据,在方法完成时被弹出,然后释放。
看一下两个局部变量相加时栈帧的内存快照
本地方法栈
这是 Java 调用操作系统本地库的地方,用来实现 JNI(Java Native Interface,Java 本地接口)
执行引擎
Java虚拟机的核心,控制装入 Java 字节码并解析;对于运行中的Java程序而言,每一个线程都是一个独立的虚拟机执行引擎的实例,从线程生命周期的开始到结束,他要么在执行字节码,要么在执行本地方法。
本地接口
连接了本地方法栈和操作系统库。
注:文中所有提到“Java虚拟机”的地方都是指“JavaEE和JavaSE平台的Java虚拟机规范”。
摘要: 在Java中,我们在实现继承的时候存在下面几个事实: 1、准备两个类,他们用extends关键字链接起来 2、如果超类没有默认构造函数,需要在子类构造函数中显式的super并传参,如果都是默认构造函数也可以super,不super虚拟机是自动的 3、子类可追加,覆盖,重载方法,子类可以有自己的私有属性,他们在子类构造函数中被构造 4、字段是数据,方法在代码区,和类建立方法表,同一个类的对象...
阅读全文
1、脚本说明
此脚本用于清空数据库数据,只删除相关表记录,保留表结构及存储过程触发器等主要架构。
设计思路:
1)根据表添加时间逆向获取所有用户表信息
2)使用游标循环删除每张表内数据
3)使用delete进行删除,即使有外键关系同样可以删除表记录
4)表存在自增主键则将其重置为0
5)截断日志,将数据库表空间及日志文件缩减到最小
2、使用说明
1)建立删除数据库存储过程SP_DaTaBaSeClear
以下是代码片段: If( object_id('SP_DaTaBaSeClear') is not null ) drop procedure SP_DaTaBaSeClear go SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE SP_DaTaBaSeClearASBegin Transaction declare @BtableName varchar(200) declare curDel cursor for select rtrim(name) from sysobjects where type = 'U' order by crdate desc open curDel declare @delSQL varchar(500) fetch next from curDel into @BtableName while( @@fetch_status = 0) begin set @delSQL = 'delete from ' + @BtableName print @delSQL exec( @delSQL ) if( ident_seed(@BtableName) is not null ) begin dbcc checkident( @BtableName, reseed, 0 ) print '种子成功置为1' end fetch next from curDel into @BtableName end close curDel deallocate curDel Commit GO |
2)执行该存储过程,执行过程中查看执行信息,如有红色信息则先手动删除红色信息表记录
-- 执行存储过程删除表数据
EXEC SP_DaTaBaSeClear
3)如仍然报出红色信息则直接执行以下语句进行删除
以下是代码片段: declare @BtableName varchar(128) declare curDel cursor for select rtrim(name) from sysobjects where type = 'U' order by crdate desc open curDel declare @delSQL varchar(255) fetch next from curDel into @BtableName while( @@fetch_status = 0) begin set @delSQL = 'delete from ' + @BtableName print @delSQL exec( @delSQL ) if( ident_seed(@BtableName) is not null ) begin dbcc checkident( @BtableName, reseed, 0 ) print '种子成功置为1' end fetch next from curDel into @BtableName end close curDel deallocate curDel |
4)最后执行脚本重置数据库大小
以下是代码片段: backup log @DataBaseName with no_log dbccshrinkdatabase(@DataBaseName) dbccupdateusage(@DataBaseName) |
1、查看当前可用的所有环境变量(=系统变量+用户变量)
set
查看某个环境变量,如PATH
set PATH
添加环境变量,如xxx=aa
set xxx=aa
将环境变量(如xxx)的值置为空
set xxx=
在某个环境变量(如PATH)后添加新的值(如d:\xxx)
set PATH=%PATH%;d:\xxx
[注]:以命令行方式对环境变量的操作只对当前窗口的应用有效!
2、Windows下JAVA用到的环境变量主要有3个:JAVA_HOME、CLASSPATH、PATH。
1)JAVA_HOME指向的是JDK的安装路径,如x:\ j2sdk1.4.2,在这路径下你应该能够找到bin、lib等目录。设置方法:JAVA_HOME=c:\ j2sdk1.4.2
2)PATH变量的作用
java程序在运行时首先在path变量所定义的路径去找java.exe,并以最先找到的为准,如果安装完j2sdk后不加设置,一般是C:\WINDOWS\system32目录。
j2sdk1.4(还有其它java开发工具如jbuilder8)在安装后会将java.exe拷贝到C:\WINDOWS\system32目录下,当执行java.exe时,需要装载这个SDK下的一些文件。
如j2sdk1.4在安装完成后,C:\WINDOWS\system32下的java.exe在运行时会在C:\Program File\java\目录下装载必需的一些文件。但安装j2sdk后一般会在PATH变量的最前面设置C:\ j2sdk1.4.2 \bin。
当先安装j2sdk1.4.2,后安装jbuilder8等开发工具时,由于jbuilder8的java.exe在拷贝到C:\WINDOWS\system32时可能覆盖了j2sdk1.4.2的java.exe,那么这时在运行的java.exe会到jbuilder8所在的目录去装载必需的一些文件。
3)CLASSPATH环境变量的作用
告诉类装载器到哪里去寻找第三方提供的类和用户定义的类。也可用使用JVM命令行参数-classpath分别为应用程序指定类路径,在-classpath中指定的类路径覆盖CLASSPATH环境变量中指定的值。
3、当机器内装有多个SDK版本时,如何查看所用的是哪个SDK?
java -verbose
在出现的屏幕信息中可以看出系统装载的是哪个目录下的文件。
4、Windows OS下设置PATH的方法
〔系统〕->〔环境〕-> 〔高级〕,在PATH变量的文本框中的最前面输入C:\ j2sdk1.4.2\bin
或在命令行窗口中执行 set path=c:\j2sdk1.4.2\bin;%path%; 这样在命令行窗口的任一路径下都可以执行java.exe程序了。或设置PATH=%JAVA_HOME%\bin;%PATH%
5、对于CLASSPATH环境变量的设置方法要加倍小心,是因为以后你出现的莫名其妙80%以上的怪问题都可能是由于CLASSPATH设置不对引起的
CLASSPATH=.\;%JAVA_HOME%\lib\tools.jar
首先要注意的是最前面的".\;",——句点反斜杠分号。这个是告诉JDK,搜索CLASS时先查找当前目录的CLASS文件。
【Troubleshooting】
编译会出现以下情况,看你是否真得都理解环境变量的设置,并能解决它。
[T1] error:java不是一个可运行的程序? 由于没有设置环境变量path
[T2] error:不能打开某个目录? 可能是忽视了path环境变量中的目录的设置顺序。
[T3] Exception on thread “main” java.lang.DoClassDefFoundError:Test?没有设置classpath的路径。