最近问题处理方法总结:
1. ADOQuery 控件加锁机制
对于多线程程序中,会涉及到可能对某张表同时执行数据库的基本操作,此时便要加锁。
具体实现:
Handle select_mutex;
select_mutex = CreateMutex(NULL,false,"selectMutex");
//上锁
if(WaitForSingleObject(select_mutex,2000)!=WAIT_TIMEOUT)
{
Try() catch ()…
}
//解锁
ReleaseMutex(select_mutex);
2. 关于多线程使用ADOQuery控件的处理
在不同线程里,建议只使用同一个ADOQuery,并且使用同一个数据库连接对象
3. EXE执行程序实现不依赖CB安装环境
▲ 在CB中,Project -> Options -> Packages -> Build with runtime packages 前面的勾去掉
▲ 附加DLL文件cc3260mt.dll
▲ 附加DLL问价borlndmm.dll
4. 关于代码格式的处理
▲ 注意源码的对齐
▲ 注意源码的缩进
这样既规范,又可以方便大括号的对应
5. 注意判断SQL语句的执行结果
在程序使用ADO控件执行SQL语句时,首先要先判断执行结果,才能进行后面的处理
例如:
If(dm->execSelect(dm->qrySelect, sql) && !dm->qrySelect->Eof )
{….}
Else
{…}
6. 灵活使用try … catch中的异常,通过捕捉异常来进行需要的处理
7. 程序中的SQL语句注意,
如果某字段的值不为字符型,要使用IntToStr或者AnsiString进行转换
8. Select语句和Insert语句的执行方法,
用open来执行,返回结果集; Insert, Update, Delete这些没有返回结果集的SQL语句,使用ExecSQL执行
9. 关于ORA数据库与SQLSERVER数据库重连的方法
判断ORA数据库的连接数据库失败的几种类型:
//分离并判断异常类型,确定异常处理方式
AnsiString subexcp = "";
subexcp = e.Message.SubString(0,9);
if((subexcp == "ORA-03114") ||
(subexcp == "ORA-12560") ||
(subexcp == "ORA-12170") ||
(subexcp == "ORA-12152") ||
(subexcp == "ORA-01012") ||
(subexcp == "ORA-00028") ||
(subexcp == "ORA-12571") //增加:包程序写入错误
)
判断SQL SERVER数据库连接失败的方法:
sql = "use master; select top 1 * from sysobjects;";
qry1->Close();
qry1->SQL->Text = sql;
try
{
qry1->Open();
}
catch(...)
{
ShowMessage("必须重连!");
return;
}
▲ 对于ORA与SQL数据库重连:
TADOConnection* newConSendGPS = GetNewConnection(dm->conSendGPS, dm->qrySelect);
if(newConSendGPS != NULL)
{
dm->conSendGPS = newConSendGPS;
dm->qrySelect->Connection = newConSendGPS;
}
else return false;
//具体处理函数
TADOConnection * __fastcall Tdm::GetNewConnection(TADOConnection* BadDBConnection, TADOQuery *query)
{
//TADOConnection * newConn = NULL;
TADOConnection* newConn = new TADOConnection(NULL); //20090227修改,这里产生数据库重连失败的原因
int times = 0;
//AnsiString sql = "use master; select top 1 * from sysobjects;";
AnsiString sql = "select * from dual";
bool flag = false;
//while(true){
while(!flag){
try
{
// if(++times > 10)
// {
// return NULL;
// }
if(newConn == NULL) newConn = BadDBConnection;
newConn->Close();
newConn->ConnectionString = BadDBConnection->ConnectionString;
newConn->Connected = true;
newConn->KeepConnection = true;
query->Connection = newConn;
query->Close();
query->SQL->Clear();
query->SQL->Add(sql);
//query->ExecSQL();
query->Open();
dm->logInfo("/n重连数据库成功!");
//delete BadDBConnection;
flag = true;
break;
}
catch(Exception &e)
{
dm->logInfo("/n重连数据库失败:%s", e.Message.c_str());
dm->logInfo("/n数据库重连...");
Sleep(3000);
//flag = false;
//return true;
}
}
return newConn;
}
▲ 只针对SQL数据库重连
// 重连数据库,只针对SQLSERVER数据库
bool __fastcall Tdm::ResetDBConnection(TADOConnection *BadDBConnection)
{
//打印到log信息
dm->logInfo("/n数据库连接出现异常,程序暂停,等待重连...");
//AnsiString connStr = BadDBConnection->ConnectionString;
//连接数据库
BadDBConnection->Close();
BadDBConnection->Connected = false; //一定要加这行代码,否则ADO查询控件无法使用
while(!BadDBConnection->Connected)
{
try
{
//BadDBConnection->Close();
//BadDBConnection->ConnectionString = connStr;
BadDBConnection->Connected = true;
//BadDBConnection->KeepConnection = true;
}
catch(...)
{
BadDBConnection->Connected = false;
dm->logInfo("重新连接数据库异常...");
Sleep(3000);
}
}
//打印log信息
dm->logInfo("/n重连数据库成功");
return true;
}
10.sysdate - 1/8640含义
表示当前时间的1秒, 1/24/60/60
11. 当出现ORA-12514:无法识别的数据库连接字符串时
是因为程序所在的文件夹带有括号,请特别注意。
强烈建议:程序文件夹最好不要用括号或者中文字体之类,应该使用规范的英文命名。
12. 数据库连接字符串
1. 对于SQL SERVER数据库
conDB->Close();
conDB->ConnectionString ="Provider=SQLOLEDB.1;Password=" +
(WideString)lpPass + ";Persist Security Info=True;User ID=" + lpUserID +
";Initial Catalog=" + lpDataBase + ";Data Source="+lpSqlServer;
"Provider=SQLOLEDB.1;Password=sasa1234;Persist Security Info=True;User ID=sa;Initial Catalog=fyc;Data Source=192.168.32.6"
2. 对于ORACLE数据库
conDB->Close();
conDB->ConnectionString ="Provider=OraOLEDB.Oracle.1;Password=" +
(WideString)lpPass + ";Persist Security Info=True;User ID=" + lpUserID +
";Data Source=" + lpDataBase + ";Extended Properties=''";
"Provider=OraOLEDB.Oracle.1;Password=watermon;Persist Security Info=True;User ID=watermon;Data Source=Dev;Extended Properties=''"
13. oracle怎样修改表名、列名、字段类型、添加表列、删除表列
ALTER TABLE 表名 RENAME TO 新表名 --修改表名
ALTER TABLE 表名 RENAME COLUMNNAME TO NAME1 --修改表列名
ALTER TABLE 表名 MODIFY NAME1 NUMBER(20) --修改字段类型
ALTER TABLE 表名 ADD 列名 VARCHAR2(40) --添加表列
ALTER TABLE 表名 DROP COLUMN COLUMNNAME --删除表列
复制表: create table new_table as select * from knowed_table
14. 关于使用logInfo
a. 包含 logdll.dll, logdll.lib logdllapi.h
b. 在头文件定义Hlog logHandle
c. 在cpp文件添加logInfo函数
15. 关于使用memcpy的一个例子
memcpy(++msg, FilePathName.c_str(), FilePathNameLength);
msg += FilePathNameLength - 1;
16. 如何生成文件
//定义文件指针(需要包含头文件#include <stdio.h>)
FILE *fp;
//打开文件
fp = fopen(FilePathName.c_str(), "a+");
//输出到文件
fprintf(fp, Msg.c_str());
//关闭文件
fclose(fp);
17. 如何定义全局变量指针
在main函数的前面定义int *pointer = (int *)malloc(5);或者 int *pointer = new int;
在要使用全局变量的类的头文件中定义extern int *pointer; //引用全局变量
18.TerminateThread()的使用
A thread cannot protect itself against TerminateThread, other than by controlling access to its handles.
不能在一个线程里面执行TerminateThread().
if(rHandle)
{
DWORD lpExitCode;
if(::GetExitCodeThread(rHandle, &lpExitCode))
{
if(lpExitCode == STILL_ACTIVE)
{
printf("/nlpExitCode = %d", lpExitCode);
//线程还在运行
printf("/n线程还在运行");
//SetEvent(m_hEventClose);
//WaitForMultipleObjects(1, &m_hEventCloseEd, TRUE, INFINITE);
}
else
{
printf("/n线程已经结束");
}
}
}
if(rHandle)
{
TerminateThread(rHandle, 0);
CloseHandle(rHandle);
rHandle = NULL;
ComDataModule->logInfo("/n关闭线程成功");
}
19.数据库连接字符串
1. 对于SQL SERVER数据库
conDB->Close();
conDB->ConnectionString ="Provider=SQLOLEDB.1;Password=" +
(WideString)lpPass + ";Persist Security Info=True;User ID=" + lpUserID +
";Initial Catalog=" + lpDataBase + ";Data Source="+lpSqlServer;
"Provider=SQLOLEDB.1;Password=sasa1234;Persist Security Info=True;User ID=sa;Initial Catalog=fyc;Data Source=192.168.32.6"
2. 对于ORACLE数据库
conDB->Close();
conDB->ConnectionString ="Provider=OraOLEDB.Oracle.1;Password=" +
(WideString)lpPass + ";Persist Security Info=True;User ID=" + lpUserID +
";Data Source=" + lpDataBase + ";Extended Properties=''";
"Provider=OraOLEDB.Oracle.1;Password=watermon;Persist Security Info=True;User ID=watermon;Data Source=Dev;Extended Properties=''"
20. 安装SQLSERVER数据库出现的问题导致无法安装
问题描述:
SQL Server 2005 卸载之后重新安装,在执行检查时报:对性能监视器计数器注册表值执行系统配置检查失败。有关详细信息,请参阅自述文件或 SQL Server 联机丛书中的“如何在 SQL Server 2005 中为安装程序增加计数器注册表项值”。
解决方案:
在开始==>运行==>regedit.exe ,在注册表里找 HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Perflib 里面有 Last Counter 和Last Help 选项查看其相应的值之后。如果你安装中文版HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Perflib/004里面找到 Counter 和Help 查看它们的最大值 ,在它们的最大值基础上加2赋给Last Counter和Last Help 确定即可,无需重启。 如果你安装的是英文版,在HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows
NT/CurrentVersion/Perflib/009里找到 Counter 和Help 查看它们的最大值,执行上面的操作即可
21 如何写SQL SERVER数据库的update触发器
1:update触发器中可以用两个系统表 分别是 inserted 和deleted
2:inserted表中存这更新后的所有数据
3:deleted表 存着更新前的所有数据
4:update(列名字)可以测试一个列是否被更新了
有了上面的知识,写update触发器就一切ok了。
22 如何写SQL SERVER数据库里创建表的SQL语句
创建新表的同时复制数据:
select * into gpsinfo_20090506 from alarmstatus
只创建新表,没有复制数据:
select * into gpsinfo_20090502 from alarmstatus where 1 = 0
创建新表的同时有条件地复制数据
select * into gpsinfo_20090502 from alarmstatus where uniqueid > 1
如果表存在,复制表数据(源表和目标表不能有自增变量)
insert into alarmstatus_1 (terminalcode, status) select terminalcode, status from alarmstatus_2
或者insert into insert into alarmstatus_1 select * from alarmstatus_2
23 如何在SQL SERVER数据库里判断某表是否存在
select count(*) as qty from dbo.sysobjects where name = 'gpsinfo_20090501'
或select count(*) qty from dbo.sysobjects where name = 'gpsinfo_20090501';
qty=0 不存在
qty=1 存在
注意:不能使用select * from gpsinfo_20090501方式来查询,否则会造成对象名无效的错误
24. gettickcount()的用法
用于计算时间,相当于计时器。当达到计时效果时,要注意重置计时为当前时间,开始重新计时。
25. 移位
Int value = 1899932 -----1CFD9C
使用三个字节表示
Char cvalue[0] = 0x1c;
Char cvalue[1] = 0xfd;
Char cvalue[2] = 0x9c;
1:
(value >>16) & 0xff
>>16:右移16位,即2个字节占用的位置,去掉低16位的数值,即得到0x1c
& 0xff : 0x001c
&0x00ff
_________
0x1c
2:
(value >>8) & 0xff
>>8:右移8位,即1个字节占用的位置,去掉低8位的数值,即得到0xfd
& 0xff : 0x00fd
&0x00ff
_________
0xfd
3:
Value & 0xff
& 0xff: 0x009c
&0x00ff
_________
0x9c
26. int,long int, unsigned int,unsigned long int,long long的表示范围问题
int和long int二者的范围是一致的,都是-2^31---2^31-1,能表示的最大值是0x7FFFFFFF;
unsigned int和unsigned long int二者的范围也是一致的,都是0---2^32-1,能表示的最大值是0xFFFFFFFF;
long long 使用的意义:
long long a;
a = atoi(inputdata);
if(a<0x1 || a>0xFFFFFFFF)
return BOOL_FALSE;
在这里,当用户恰好输入0xFFFFFFFF这个值时,程序就不会认为它是非法的。但是当使用int a或者unsigned int a时程序将会认为非法输入。
27. 关键字static 的作用是什么?
这个简单的问题很少有人能回答完全。在C 语言中,关键字static 有三个明显的作用:
• 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
• 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
• 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。
28. 几种变量的定义
a) int a;
b) int *a;
c) int **a;
d) int a[10];
e) int *a[10];
f) int (*a)[10];
g) int (*a)(int);
h) int (*a[10])(int);