2012-11-19 15 views
0

我在c程序中提示用戶輸入產品製造商,並應根據用戶輸入查詢來打印製造商生產的所有產品,不管它們是PC ,筆記本電腦或打印機。什麼是錯的但是在這裏,我得到兩個SQL狀態返回一行後:使用db2在C程序中嵌入SQL

SQLSTATE-02000和SQLSTATE = 24000

這些都不是,我已經搜查了SQL錯誤代碼。

下面我已經包含了我的.c文件和我正在使用的.sql模式。

任何幫助,非常感謝。

#include <stdio.h> 
    #include <stdlib.h> 

    /*** header file for ORACLE definitions ***/ 
    exec sql include sqlca; 

    int print_sql_state(char *code){ 
    printf("\nSQLSTATE=%s\n", code); 
    } 

    int main() 
    { 
    /*** Variable Declaration Block ***/ 
    exec sql begin declare section; 
     char login[129], password[129]; 
     char SQLSTATE[6]; 

     /*query based on*/ 
     char maker[40]; 
     /*results based on product*/ 
      int model; 
      char type[40]; 
     /*results based on type of product*/ 
      float speed; 
      int ram; 
     int hd; 
     float screen; 
     int price; 
    exec sql end declare section; 

    /*** handler for error ***/ 
    exec sql whenever sqlerror goto report_error; 
    exec sql whenever not found goto notfound; 



    /*** Prompt user for login name and password ***/ 
    printf("Username="); 
    gets(login); 
    printf("Password="); 
    char *pass_string = malloc(128); 
    pass_string=getpass(""); 
    strcpy(password, pass_string); 

    /*** Connect to DB ***/ 
    exec sql connect :login 
     identified by :password; 

    printf("\nCONNECTION SUCCESSFUL\n"); 

     /*** INSERT RECORD WITH VALUES PROVIDED BY USER ***/ 
    while(1){ 
     printf("\nInput manufacturer:"); 
     scanf("%s", &maker); 
     if (maker==-1) /* end loop */ 
     return 0; 

      /*** cursor declaration ***/ 
     exec sql declare specs_1 cursor for 
      SELECT P.model, P.speed, P.ram, P.hd, P.price 
      FROM Product PR, PC P 
      WHERE PR.model = P.model AND PR.maker = :maker 
      UNION 
      SELECT L.model, L.speed, L.ram, L.hd, L.price 
      FROM Product PR, Laptop L 
      WHERE PR.model = L.model AND PR.maker = :maker; 

      /*seperate query since not Union Compatible*/ 
     exec sql declare specs_2 cursor for 
      SELECT P.model, P.price 
      FROM Product PR, Printer P 
      WHERE PR.model = P.model AND PR.maker = :maker; 

     exec sql open specs_1; 
     /*** TRAVERSE RESULT SET WITH CURSOR ***/ 
     while(1){ 
      EXEC SQL 
      FETCH specs_1 into :model, :speed, :ram, :hd, :price; 
      printf("\nModel = %d, Speed = %f, Ram = %d, hd = %d, Price = %d", 
          model, speed, ram, hd, price); 
     } 

     exec sql open specs_2; 
     /*** TRAVERSE RESULT SET WITH CURSOR ***/ 
     while(1){ 
      EXEC SQL 
      FETCH specs_2 into :model, :price; 
      printf("\nModel = %d, Price = %d", model, price); 
     } 

      continue; 
     exec sql close specs_1; 
     exec sql close specs_2; 

     notfound: 
      printf("\nNO DATA"); 
      print_sql_state(SQLSTATE); 
      exec sql close specs_1; 
      exec sql close specs_2; 
    } 


    report_error: 
     printf("\nCONNECTION ERROR\n"); 
     print_sql_state(SQLSTATE); 
     return 1;   
    } 

和SQL

CREATE TABLE Product(
     maker VARCHAR(50), 
     model INTEGER PRIMARY KEY, 
     type VARCHAR(10) /*PC, Laptop, or Printer*/ 
    ); 

    CREATE TABLE PC(
     model INTEGER PRIMARY KEY, /*model number*/ 
     speed REAL, 
     ram INTEGER, 
     hd INTEGER, 
     price INTEGER /*"in dollars"*/ 
     ; 

    CREATE TABLE Laptop(
     model INTEGER PRIMARY KEY, 
     speed REAL, 
     ram INTEGER, 
     hd INTEGER, 
     price INTEGER, 
     screen INTEGER 
    ); 

    CREATE TABLE Printer(
     model INTEGER PRIMARY KEY, /*model number*/ 
     price INTEGER /*"in dollars"*/ 
    ); 

編輯:::我的程序的輸出打字的時候 '戴爾' 的 「製造者」

Username=me 
    Password= 

    CONNECTION SUCCESSFUL 

    Input manufacturer:Dell 

    Model = 1, Speed = 3.400000, Ram = 4000, hd = 125, Price = 999 
    NO DATA 
    SQLSTATE=02000 

    CONNECTION ERROR 

    SQLSTATE=24000 

編輯::這是測試插入我一直在使用。

INSERT INTO Product Values('Alien', 5, 'PC'); 
    INSERT INTO PC Values(5, 3.0, 8000, 500, 1299); 

    INSERT INTO Product Values('HP', 7, 'PC'); 
    INSERT INTO PC Values(7, 3.0, 8000, 500, 2899); 

    INSERT INTO Product Values('Toshiba', 8, 'PC'); 
    INSERT INTO PC Values(8, .3, 1000, 20, 299, 10); 

    INSERT INTO Product Values('Dell', 1, 'Laptop'); 
    INSERT INTO Laptop Values(1, 3.4, 4000, 125, 999, 13); 

    INSERT INTO Product Values('Sony', 4, 'Laptop'); 
    INSERT INTO Laptop Values(4, 1.2, 2000, 20, 299, 10); 

    INSERT INTO Product Values('HP', 2, 'Laptop'); 
    INSERT INTO PC Values(2, 1.0, 8000, 500, 899, 19); 

    INSERT INTO Product Values('Toshiba', 9, 'Laptop'); 
    INSERT INTO Laptop Values(9, .4, 900, 20, 299, 10); 

    INSERT INTO Product Values('Toshiba', 10, 'Laptop'); 
    INSERT INTO Laptop Values(10, .4, 900, 20, 299, 13); 

    INSERT INTO Product Values('Toshiba', 11, 'Laptop'); 
    INSERT INTO Laptop Values(11, .4, 900, 20, 299, 10); 

    INSERT INTO Product Values('Toshiba', 12, 'Laptop'); 
    INSERT INTO Laptop Values(12, .4, 900, 20, 299, 19); 

    INSERT INTO Product Values('Dell', 3, 'Printer'); 
    INSERT INTO Printer Values(3, 199); 

    INSERT INTO Product Values('Kodak', 6, 'Printer'); 
    INSERT INTO Printer Values(6, 300); 

回答

0

SQL錯誤代碼將是SQLCODE而不是SQLSTATE。 2000年的SQLSTATE只是意味着沒有更多的行。 24000意味着光標處於無效狀態,這是我所期望的,如果你繼續使用它。您應該檢查代碼之外的語句,以確保您做到可以獲得多行。


話雖如此,你的代碼中也有一些可疑的東西。首先是你爲密碼分配128字節,然後通過將指針設置爲返回值getpass()立即泄漏它。第二個是你的外環退出條件,當maker == -1導致休息。由於maker是一個字符數組,它永遠不會是 -1。

您還應該檢查(並告訴我們)程序的實際輸出 - 這將爲問題的發生提供重要線索。


而且,基於你的insert語句,你將得到一行。您插入戴爾筆記本電腦和戴爾打印機,但您的第一個光標查詢僅查找筆記本電腦和PC(其中分別有1個和0個)。

因此2000(沒有更多數據)是來自數據庫的正確響應。

現在你可能會認爲你的第二個查詢應該拿起打印機,並且它會運行。不幸的是,由於第一個查詢中沒有「數據」,第二個查詢被完全跳過,並返回到外部循環。

如果您將打印機位添加爲另一個聯合並僅爲速度,RAM和HD大小選擇常量,則可以將其作爲單個查詢來執行。當然,你需要一個額外的列來區分這兩種類型(有和沒有這些字段)。

或者,您可以爲每個查詢提供自己的錯誤處理代碼,以便第一次停止時不會跳過第二個查詢。

+0

謝謝paxdiablo。我正在使用「數據庫管理系統」第3版,其中規定了以下關於錯誤代碼的內容:「SQLCODE是兩者中較早的一個,並且被定義爲當出現錯誤條件時返回一些負值,而沒有進一步指定什麼錯誤特定的負整數表示SQLSTATE首次引入SQL-92標準,它將預定義的值與幾個常見的錯誤條件關聯起來,從而在報告錯誤的方式上引入了一些統一性。 – Matt

+0

我已經將輸出添加到程序中。也會添加插入,因爲它沒有報告應該輸出的所有輸出: - \ – Matt

+0

@ Matt8541,基於您的補充,DB2正在做正確的事情。 – paxdiablo