藍森林首頁 | 返回主頁 | 本站地圖 | 站內搜索 | 聯繫信箱 |
 您目前的位置:首頁 > 自由軟件 > 技術交流 > 應用編程


    

藍森林 http://www.lslnet.com 2006年6月6日 10:18


在pro*c中出問題了!

我在程序中調用insert語句,出現了下面錯誤的語句:
ORA-1480: trailling null missing from STR bind value

這是什麼原因??怎麼會發生這樣的錯誤呢?
謝謝!!

在pro*c中出問題了!

你使用的是pro*c還是途徑

另外使用的是varchar類型的還是char類型的

在pro*c中出問題了!

我使用的是pro*C
我的表中的類型有NUMBER, VARCHAR2
定義的插入的變量全都是char數組 類型。
書上說NUMBER和char是可以互換的。這樣會有問題嗎?

在pro*c中出問題了!

你檢查一下數據類型的長度,這個問題應該是數據類型的長度超過了數據庫中的定義!

在pro*c中出問題了!

我的NUMBER和VARCHAR2中最大的定義為20個字符,請問是不是這個地方出問題了。
我的列也定義得很長,最大的有10個字符那麼大,這樣有問題嗎??

在pro*c中出問題了!

不好說,出現這個錯誤報告應該是數據類型的長度不匹配,你仔細的查查,如果可以的話是否可以把那段錯誤程序貼一下.

在pro*c中出問題了!

錯誤信息就是說你插入的數據沒有以NULL結束.

在pro*c中出問題了!

不好意思,我的程序不在手上。
我插入的數據是從客戶端接受的,我是不是要在每個字符串後都加上'\0'才對呢?

在pro*c中出問題了!

能否將你插入數據庫的那條語句,發出來看一下,我覺得應該是你語句寫的有問題吧?我以前用Pro*C沒有遇到過這種問題呀

在pro*c中出問題了!

[code]

#include <unistd.h>;
#include <stdlib.h>;
#include <fcntl.h>;
#include <sys/types.h>;
#include <sys/wait.h>;
#include <signal.h>;
#include <errno.h>;
#include <stdio.h>;
#include <string.h>;
#include <sys/types.h>;
#include <sys/socket.h>;
#include <netinet/in.h>;
#include <arpa/inet.h>;
#include <sys/time.h>;

EXEC SQL INCLUDE SQLCA;
EXEC SQL INCLUDE ORACA;

EXEC SQL BEGIN DECLARE SECTION;
char uid[]="test/test";

struct tab_main_data{
    char c_account_id[20];
    char dep_open_id[8];
    char dep_cur_id[8];
    char c_name[20];
    char c_passwd[6];
    char c_open_day[10];
    char c_status_flag[2];
    char c_saved[11];
    char c_cancel_flag[2];
    char op_id[20];
    char c_saved_day[10];
}TMD;
EXEC SQL END DECLARE SECTION;

/* There is the declaration section*/

void account_open(char *, int);
void SetAccountInfoToTMD(char *, struct tab_main_data *);
void select_error(int);


/*
*  account_open() is used to open an count for a customer
*  and write the info of customer into the table "tab_main_data"
*/

void account_open(char *buf, int sockfd)
{
    SetAccountInfoToTMD(buf, &TMD);

    EXEC SQL WHENEVER SQLWARNING CONTINUE;
    EXEC SQL WHENEVER SQLERROR DO select_error(sockfd);
    EXEC SQL INSERT INTO tab_main_data(c_account_id, dep_open_id,    \
            dep_cur_id, c_name, c_passwd, c_open_day, c_status_flag,    \
            c_saved, c_cancel_flag, op_id, c_saved_day)    \
        VALUES(:TMD.c_account_id, :TMD.dep_open_id, :TMD.dep_cur_id,    \
            :TMD.c_name, :TMD.c_passwd, :TMD.c_open_day,    \
            :TMD.c_status_flag, :TMD.c_saved, :TMD.c_cancel_flag,    \
            :TMD.op_id, :TMD.c_saved_day);
printf("account_open(): add an account success!\n");
}

void SetAccountInfoToTMD(char *buf, struct tab_main_data *pInfo)
{
    buf+=1;
    strncpy(pInfo->;c_account_id, buf, 20);
printf("%-8s\n",pInfo->;c_account_id);
    buf+=20;
    strncpy(pInfo->;dep_open_id, buf, 8);
printf("%s\n",pInfo->;dep_open_id);
//    strncpy(pInfo->;dep_cur_id, buf, 8);
    strncpy(pInfo->;dep_cur_id, pInfo->;dep_open_id, 8);
printf("%s\n",pInfo->;dep_cur_id);
    buf+=8;
    strncpy(pInfo->;c_name, buf, 20);
printf("%-8s\n",pInfo->;c_name);
    buf+=20;
    strncpy(pInfo->;c_passwd, buf, 6);
printf("%-8s\n",pInfo->;c_passwd);
    buf+=6;
    strncpy(pInfo->;c_open_day, buf, 10);
printf("%-8s\n",pInfo->;c_open_day);
    buf+=10;
    strncpy(pInfo->;c_status_flag, buf, 2);
printf("%-8s\n",pInfo->;c_status_flag);
//    bcopy(buf, pInfo->;c_status_flag, sizeof(char));
    buf+=2;
    strncpy(pInfo->;c_saved, buf, 11);
printf("%-8s\n",pInfo->;c_saved);
    buf+=11;
    strncpy(pInfo->;c_cancel_flag, buf, 2);
printf("%-8s\n",pInfo->;c_cancel_flag);
//    bcopy(buf, pInfo->;c_status_flag, sizeof(char));
    buf+=2;
    strncpy(pInfo->;op_id, buf, 20);
printf("%-8s\n",pInfo->;op_id);
    buf+=20;
    strncpy(pInfo->;c_saved_day, buf, 10);
printf("%-8s\n",pInfo->;c_saved_day);
}


void select_error(int sockfd)
{
    char err_buf[100];

    sprintf(err_buf, "%.*s", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
    if(write(sockfd, err_buf, sizeof(err_buf))==-1)
    {
        printf("select_error(): write error");
    }
printf("%s", err_buf);

    EXEC SQL WHENEVER SQLERROR CONTINUE;
    EXEC SQL ROLLBACK WORK RELEASE;
    exit(-1);
}


[/code]

以上就是三個函數就是出問題的地方,請各位幫幫忙!

void SetAccountInfoToTMD(char *buf, struct tab_main_data *pInfo)
這個函數是用來把收到的數據包寫進TMD這個結構,裡面的的printf語句用於測試收到到的結果是否正確,經過測試客戶端(用kylix/delphi寫的)發來的數據都能正確顯示。

請問我的問題出在哪了??

在pro*c中出問題了!

程序重用strncpy(pInfo->;c_cancel_flag, buf, 2);
應該沒什麼問題的,我覺得你有必要察看一下數據庫中字段定義信息。

在pro*c中出問題了!

我同意樓上大哥的建議,仔細查看你每一個數據庫中字段的定義,然後再對應查看你給其賦的值的類型是否與字段類型匹配

在pro*c中出問題了!

希望高手門能看明白以下我說什麼,我的表達能力實在很差勁!見諒!

我的問題解決了,不是數據庫中字段的定義有問題。
問題出在我接收字符串的函數void SetAccountInfoToTMD(char *, struct tab_main_data *);

客戶端是把數據放進一個string的變量發過來的,而我在void SetAccountInfoToTMD(char *, struct tab_main_data *);
這個函數里卻沒有用'\0'截取每個字符串,而是想當然的以為strncpy把我想要的N個字符拷貝到struct結構裡的成員,struct結構裡的變量就有了我預期的值。
我的理解是這樣的,我定義的struct tab_main_data裡的成員全都是字符串類型,結構裡的變量是用一塊連續的空間存放的,由於沒有用'\0'標誌每個字符串變量的結束,所以結構裡的的第一個變量存放的就是整個讀出來的數據,而不是預期的其中一個數據,所以就出問題了。不知道我這樣理解對不對?

我還有一點不明白,我要改了以下兩個地方才能把所有數據完整的取出來,否則每個成員變量就會少取最後一個字符,即比原來的想取的字符串少了一個字符。
照理說,如:
char c_account_id[20];就可以存放21個字符了,但是為什麼我要寫成
char c_account_id[21];才能把20個字符全部放進去了呢?
[code]

EXEC SQL BEGIN DECLARE SECTION;
char uid[]="test/test";

struct tab_main_data{
    char c_account_id[21];
    char dep_open_id[9];
    char dep_cur_id[9];
    char c_name[21];
    char c_passwd[7];
    char c_open_day[11];
    char c_status_flag[3];
    char c_saved[12];
    char c_cancel_flag[3];
    char op_id[21];
    char c_saved_day[11];
}TMD;
EXEC SQL END DECLARE SECTION;

.........
..........
.........

void SetAccountInfoToTMD(char *buf, struct tab_main_data *pInfo)
{
    buf+=1;
    strncpy(pInfo->;c_account_id, buf, 20);
pInfo->;c_account_id[21]='\0';       《====這裡要是寫成pInfo->;c_account_id[20]='\0';       就會只截取19個字符,而不是我想要的20個字符,怎麼會這樣呢??以下各個變量也是這樣。。。
    buf+=20;
    strncpy(pInfo->;dep_open_id, buf, 8);
pInfo->;dep_open_id[9]='\0';
    strncpy(pInfo->;dep_cur_id, pInfo->;dep_open_id, 8);
    buf+=8;
    strncpy(pInfo->;c_name, buf, 20);
pInfo->;c_name[21]='\0';
    buf+=20;
    strncpy(pInfo->;c_passwd, buf, 6);
pInfo->;c_passwd[7]='\0';
    buf+=6;
    strncpy(pInfo->;c_open_day, buf, 10);
pInfo->;c_open_day[11]='\0';
    buf+=10;
    strncpy(pInfo->;c_status_flag, buf, 2);
pInfo->;c_status_flag[3]='\0';
    buf+=2;
    strncpy(pInfo->;c_saved, buf, 11);
pInfo->;c_saved[12]='\0';
    buf+=11;
    strncpy(pInfo->;c_cancel_flag, buf, 2);
pInfo->;c_cancel_flag[3]='\0';
    buf+=2;
    strncpy(pInfo->;op_id, buf, 20);
pInfo->;op_id[21]='\0';
    buf+=20;
    strncpy(pInfo->;c_saved_day, buf, 10);
pInfo->;op_id[11]='\0';
}

[/code]

在pro*c中出問題了!

因為還有\0要佔一個字符

另外strncpy
如果源比目的串找
那麼不會在最後自動加\0

我原來分析時也沒有認真看

在pro*c中出問題了!

是的,Strncpy函數是不會自動帶拷貝的字符串後面加"\0"的.另外如果你定義的字符串長度應該比數據庫中的定義多一位,因為在C語言裡面字符串是要用"\0"字符來表示結束的.

在pro*c中出問題了!

謝謝 無雙 robinliu76 !!



Copyright © 1999-2000 LSLNET.COM. All rights reserved. 藍森林網站 版權所有。 E-mail : webmaster@lslnet.com