为什么我不能在连接到C的SQLite中创建两个新用户?打两个电话都不管用



我不明白为什么会发生这种情况。什么可能是逻辑错误,或者我如何解决它。事实上,问题是即使我执行客户登录(不是这里代码的一部分(,然后尝试注册也会出现同样的问题。但我可以多次登录和注销。我可以创建一个新用户并使用登录

#include<stdlib.h>
#include<string.h>
#include "sqlite3.c" 
char output[5][30];//to save result
int temp;//global variable to be used in callback again
typedef struct usr{char name[15],pass[15];int uid;}USER;
static int callback(void *data, int argc, char **argv, char **azColName)
{
int i;
temp=argc;//stores number of return values
printf("n*%d*n",argc);
for(i=0;i<argc;i++)
{
strcpy(output[i],argv[i]);
printf("*%s* ",argv[i]);
}
return 0;
}
void INSERTC()
{
printf("nntttttttttttttCustomer Signup");
sqlite3 *db;
char *zErrMsg = 0;
int t,rc,*data;
char sql[150],name[30],pass[30];
printf("ntEnter your Username : ");
scanf("%s",name);
printf("ntEnter your Password : ");
scanf("%s",pass);
rc = sqlite3_open("trail1.db", &db);
sprintf(sql, "SELECT userid FROM customer WHERE username='%s';",name);
rc = sqlite3_exec(db, sql,callback,(void*)data, &zErrMsg);//callback is called for every line in result
if(temp==0)
{   
strcpy(sql,"SELECT COUNT(*) FROM customer;");
rc = sqlite3_exec(db, sql,callback,(void*)data, &zErrMsg);
t=atoi(output[0]);
sprintf(sql,"INSERT INTO customer(userid,username,password) VALUES(%d,'%s','%s');",t,name,pass);
rc = sqlite3_exec(db, sql,callback,(void*)data, &zErrMsg);
printf("ntSuccessfully Registered.n");
printf("ntUser Id Alloted : %d",t);
sqlite3_close(db);
}
else
printf("ntUsername already taken!");
printf("nntPress Enter to continue...");
getchar();getchar();
}
int main(int argc, char* argv[])
{
INSERTC();//First call
INSERTC();//Second call
return 0;
}

代码执行前的表格代码执行

在代码中,我所做的是搜索给定的用户名,如果查询没有返回结果,我会插入记录。如果返回,则打印已使用的用户名。

问题1

您可以根据变量temp来决定是否已经使用了用户名。

此参数设置为回调的argc参数。当您运行第一个INSERTC调用时,下面语句SELECT COUNT(*) FROM customer的回调将temp设置为1,因为有一个结果列COUNT(*)。实际结果是带有回调的argv参数的字符串。

文件显示:

sqlite3_exec((回调函数的第二个参数是结果中的列数。sqlite3_exec((回调的第三个参数是指向字符串的指针数组,这些指针就像从sqlite3_column_text((获得的一样,每列一个。

请参阅https://www.sqlite.org/c3ref/exec.html

问题2

但实际上,您似乎想在之前用SELECT userid FROM customer WHERE username='%s'检查temp。但是,如果找不到具有匹配用户名的记录,则不会调用回调。

数据指针

指针*数据从未初始化。

sqlite3_exec((的第4个参数被中继到每个回调调用的第1个参数。

由于您不使用数据指针,您可以直接传递NULL。如果你想利用它,一定要初始化它

返回代码

sqlite3函数返回一个代码,指示操作是否成功。您应该检查操作是否成功,并在失败时采取适当的操作(例如,将错误消息打印到stderr并以错误代码结束(。

关闭数据库连接

只能在if分支中调用sqlite3_close。但你应该独立于结果来关闭它。

更好地使用准备好的报表

您不应该使用sprintf来创建包含未检查的外部用户输入的自己的SQL,而应该使用准备好的语句。使用未经检查的用户输入可能会导致最严重的安全风险之一,即SQL注入。

因此,最好使用sqlite3_prepare_v2((、sqlite3_step((和sqlite3_finalize((。基本上,sqlite3_exec只是这些调用的一个方便的包装器。关于如何使用它的示例,您可以查看https://stackoverflow.com/a/57505795/2331445.

这种方法的另一个优点是,您可以在同一个地方处理SQL调用和相关的结果。

最新更新