使用db2在C程序中嵌入SQL

使用db2在C程序中嵌入SQL,sql,c,db2,Sql,C,Db2,我有一个c语言的程序,提示用户输入产品制造商,并根据用户输入进行查询,以打印制造商生产的所有产品,无论是PC、笔记本电脑还是打印机。但是,这里有点不对劲,因为在返回一行之后,我得到了两个sql状态: SQLSTATE-02000和SQLSTATE=24000 这两个都不在我搜索过的sql错误代码中 下面是我的.c文件和正在使用的.sql模式 非常感谢您的帮助 #include <stdio.h> #include <stdlib.h> /*** header

我有一个c语言的程序,提示用户输入产品制造商,并根据用户输入进行查询,以打印制造商生产的所有产品,无论是PC、笔记本电脑还是打印机。但是,这里有点不对劲,因为在返回一行之后,我得到了两个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;           
  }
编辑:::将“Dell”键入为“maker”时程序的输出

编辑::这些是我一直在使用的测试插入

  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);
SQL错误代码将位于SQLCODE中,而不是SQLSTATE中。SQLSTATE为2000表示不再有行。24000意味着游标处于无效状态,如果继续使用它,我会想到这一点。您可能应该检查代码外部的语句,以确保获得多行


话虽如此,代码中也有一些可疑的东西。第一种方法是为密码分配128字节,然后通过将指针设置为返回值
getpass()
,立即泄漏密码。第二个是外部循环的退出条件,当
maker==-1
导致中断时。因为
maker
是一个字符数组,所以它永远不会是-1

您还应该检查(并告诉我们)您的程序的实际输出,这将为问题发生的位置提供重要线索


并且,根据insert语句,您只能得到一行。插入Dell笔记本电脑和Dell打印机,但第一次光标查询仅查找笔记本电脑和PC(其中分别有1和0)

因此,2000(无更多数据)是来自数据库的正确响应

现在,您可能认为您的第二个查询应该选择打印机,如果它已经运行的话,它会选择打印机。不幸的是,由于第一个查询的“无数据”,第二个查询被完全跳过,并返回到外部循环

如果您将打印机位添加为另一个并集,并且只选择速度、RAM和HD大小的常量,则可以将其作为单个查询来执行。当然,您需要一个额外的列来区分这两种类型(有和没有这些字段)


或者,您可以为每个查询提供自己的错误处理代码,以便在第一个查询停止时不会跳过第二个查询。

谢谢您paxdiablo。我正在使用“数据库管理系统”ed 3一书,该书对错误代码进行了如下说明:SQLCODE是两者中较早的一个,定义为在出现错误条件时返回一些负值,而不进一步指定特定负整数表示的错误。SQL-92标准中首次引入的SQLSTATE将预定义值与几个常见错误条件相关联,从而在报告错误的方式上引入了一些一致性。我已将输出添加到程序中。我还将添加insert,因为它没有报告它应该报告的所有输出:-\@Matt8541,根据您添加的内容,DB2做的是正确的。有关详细信息,请参阅我的更新。
  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);