全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2769
推到 Plurk!
推到 Facebook!

Delphi中往SQL数据库表里写数据之主键约束问题

缺席
keykill
一般會員


發表:5
回覆:8
積分:2
註冊:2009-03-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-03-24 11:39:29 IP:222.95.xxx.xxx 訂閱
毕业设计,做的是银行家算法,用delphi实现其改进与仿真
遇到个问题,我的数据库里有个表_P_R设置了两个主键,分别是进程ID(p_id)和资源ID(r_id)
然后我使用ADOTable通过以下代码往表里写数据
for i:=1 to rnum do
for j:=1 to pnum do
begin
ADOTable1.Insert;
ADOTable1.FieldByName('p_id').AsInteger:=i;
ADOTable1.FieldByName('r_id').AsInteger:=j;
ADOTable1.Post;
end
然后运行的时候一直报错,说违反了主键约束

有两个主键,p_id和r_id都相同时才算违反主键约束吧?
我肯定得往数据库里写入(1,1)(1,2)(1,3)之类的啊....(在SQL企业管理器里面是能这样写入的啊)
各位大虾,怎么办?


网易邮箱,中国第一大电子邮件服务商
keykill
一般會員


發表:5
回覆:8
積分:2
註冊:2009-03-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2009-03-27 15:33:52 IP:222.95.xxx.xxx 訂閱
没人会的?难道这个问题是不可解决的?....
BOSS
中階會員


發表:70
回覆:79
積分:64
註冊:2006-11-01

發送簡訊給我
#3 引用回覆 回覆 發表時間:2009-03-27 21:31:53 IP:123.194.xxx.xxx 訂閱
(1,1)不就已經重複了
===================引 用 keykill 文 章===================
没人会的?难道这个问题是不可解决的?....
keykill
一般會員


發表:5
回覆:8
積分:2
註冊:2009-03-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2009-03-27 22:45:58 IP:222.95.xxx.xxx 訂閱
解释一下,我设置两个主键,也是就是联合主键,需要两个值(两列值)来确定一条记录
可能发的帖有歧异,,现在说明一下
"两个都相同",是指N组(p_id,r_id)中,如果有两组,p_id,r_id的值都相同才算违反主键约束.
比如说
(1,1)
(1,2)
(1,3)
(1,4)
(2,1)
(2,2)
(2,3)
(2,4)
这些都没有违反主键约束,但如果再插入一组值(1,2)就违反了主键约束....

我很急啊...希望高手速度帮帮忙啊...小弟感激不尽
AndrewK
高階會員


發表:6
回覆:151
積分:161
註冊:2006-10-09

發送簡訊給我
#5 引用回覆 回覆 發表時間:2009-03-28 00:34:26 IP:60.250.xxx.xxx 訂閱
我試過您的程式碼
須多加一行 code
不然會出現 "can't not perform this operation on a closed dataset "

但你出現 "primary key error "

你可能要檢查你的
1.資料庫設定、資料庫的內容
2.adotable 的設定 (假設是一開始執行就報錯的話)

如果您可以貼上您的錯誤訊息,以對 adotable 的設定值
也許大家會比較了解您的情況
------
Just Do It
-------------------------
其實男生不是真的喜歡你不減肥,而是喜歡你愛吃還不肥;也不是真的喜歡你不化妝,而是喜歡你素顏也好看;也不是真的喜歡你瘦,而是喜歡你瘦卻有胸;也不是真喜歡你獨立,而是他忙的時候別煩他。女孩子,太認真你就輸了。
keykill
一般會員


發表:5
回覆:8
積分:2
註冊:2009-03-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2009-03-28 23:51:58 IP:222.95.xxx.xxx 訂閱

[code delphi]
unit Umain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ComCtrls, ImgList, ToolWin, Buttons, DBCtrls, Grids,
DBGrids, Mask, StdCtrls, ExtCtrls, DB, ADODB;

type
TForm1 = class(TForm)
StatusBar1: TStatusBar;
MainMenu1: TMainMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
ToolBar1: TToolBar;
ImageList1: TImageList;
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
TabSheet3: TTabSheet;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Memo1: TMemo;
GroupBox1: TGroupBox;
Label1: TLabel;
Label2: TLabel;
Button4: TButton;
GroupBox2: TGroupBox;
Button6: TButton;
Edit1: TEdit;
Edit2: TEdit;
GroupBox3: TGroupBox;
Label3: TLabel;
Label4: TLabel;
Button5: TButton;
Edit3: TEdit;
Label8: TLabel;
Label9: TLabel;
Label10: TLabel;
Label11: TLabel;
Label12: TLabel;
Edit4: TEdit;
Edit5: TEdit;
Edit6: TEdit;
Edit7: TEdit;
Edit8: TEdit;
Button7: TButton;
GroupBox4: TGroupBox;
Label16: TLabel;
Label17: TLabel;
ComboBox4: TComboBox;
ComboBox5: TComboBox;
ComboBox6: TComboBox;
Label14: TLabel;
Button8: TButton;
GroupBox5: TGroupBox;
DataSource1: TDataSource;
PageControl2: TPageControl;
TabSheet4: TTabSheet;
TabSheet5: TTabSheet;
Label5: TLabel;
DBGrid1: TDBGrid;
Button9: TButton;
DBText1: TDBText;
ADOQuery1: TADOQuery;
ADOTable1: TADOTable;
TabSheet6: TTabSheet;
Label6: TLabel;
DBGrid2: TDBGrid;
Label13: TLabel;
DBGrid3: TDBGrid;
TabSheet7: TTabSheet;
Button10: TButton;
Button11: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure N3Click(Sender: TObject);


private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
rnum,pnum: integer;

implementation
{$R *.dfm}


procedure TForm1.Button4Click(Sender: TObject);
var
r,p,i,j:integer;

begin
r :=strtoint(Edit1.Text);
p :=strtoint(Edit2.Text);
if (r<0) or (r>6) or (p<0) or (p>25) then
begin
showmessage('资源类数请限制在1-5之间;进程总数请限制在1-24之间');
Edit1.Clear;
Edit2.Clear;
exit;
end
else
begin
rnum:=r;
pnum:=p;
ADOTable1.TableName:='_P_R';
ADOTable1.Active:=True;
for i:=1 to ADOTable1.RecordCount do
begin
ADOTable1.Delete;
ADOTable1.Refresh;
ADOTable1.next;
end;
for i:=1 to rnum do
for j:=1 to pnum do
begin
ADOTable1.Insert;
ADOTable1.FieldByName('p_id').AsInteger:=i;
ADOTable1.FieldByName('r_id').AsInteger:=j;
ADOTable1.Post;
end
end
end;
end.
[/code]
表_P_R里的字段分别是p_id,r_id,allocation,b_max,need,request 都是int 其中p_id,和r_id是联合主键
我通过ADOTable1用同样的方法往另一个只有一个主键的表里写过数据,成功了,只是换这个有两个主键的表就不行了......
BOSS
中階會員


發表:70
回覆:79
積分:64
註冊:2006-11-01

發送簡訊給我
#7 引用回覆 回覆 發表時間:2009-03-29 18:19:00 IP:123.194.xxx.xxx 訂閱
按照你提供的table 結構及程式,沒有key值重複的問題
sql2000 D6
keykill
一般會員


發表:5
回覆:8
積分:2
註冊:2009-03-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2009-03-29 19:40:17 IP:222.95.xxx.xxx 訂閱
SQL2000里这样定义当然没问题
问题是在我上面的delphi代码里,我用ADOTable1往里面写数据就出现问题了....
AndrewK
高階會員


發表:6
回覆:151
積分:161
註冊:2006-10-09

發送簡訊給我
#9 引用回覆 回覆 發表時間:2009-03-30 02:22:20 IP:60.250.xxx.xxx 訂閱

  1. if (r<0) or (r>6) or (p<0) or (p>25) then
    begin
  2. showmessage('资源类数请限制在1-5之间;进程总数请限制在1-24之间');
  3. Edit1.Clear;
  4. Edit2.Clear;
  5. exit;
  6. end
  7. else
  8. begin
  9. rnum:=r;
  10. pnum:=p;
  11. ADOTable1.TableName:='_P_R';
  12. ADOTable1.Active:=True;
  13. for i:=1 to ADOTable1.RecordCount do
  14. begin
  15. ADOTable1.Delete;
  16. ADOTable1.Refresh;
  17. ADOTable1.next;
  18. end;
  19. for i:=1 to rnum do
  20. for j:=1 to pnum do
  21. begin
  22. ADOTable1.Insert;
  23. ADOTable1.FieldByName('p_id').AsInteger:=i;
  24. ADOTable1.FieldByName('r_id').AsInteger:=j;
  25. ADOTable1.Post;
  26. end
  27. end
  28. if (r<0) or (r>6) or (p<0) or (p>25) then
    1. 如果你是要限制 r值 為 1-5 之间與 P值為 1-24之间的話
  29. 這個條件敘述總覺得怪怪的
  30. 2.你有試著當發生錯誤時,看一下資料庫內容嗎???
  31. 假設這是在測試階段的話, 每執行一次我會清空 table ,以方便測試
  32. 3.可以研究一下 TADOTable ,應該有設欄位主鍵的設定方式
  33. 4.通常 sql 2000 可以,2005 的環境也是可以
  34. 測試環境: sql server 2005 , D2006
  35. 測試結果: 沒有任何問題
  36. 加油吧~~ 這麼多人在幫你~
------
Just Do It
-------------------------
其實男生不是真的喜歡你不減肥,而是喜歡你愛吃還不肥;也不是真的喜歡你不化妝,而是喜歡你素顏也好看;也不是真的喜歡你瘦,而是喜歡你瘦卻有胸;也不是真喜歡你獨立,而是他忙的時候別煩他。女孩子,太認真你就輸了。
編輯記錄
AndrewK 重新編輯於 2009-04-01 22:03:58, 註解 無‧
AndrewK 重新編輯於 2009-04-01 22:06:05, 註解 無‧
AndrewK 重新編輯於 2009-04-01 23:49:57, 註解 無‧
keykill
一般會員


發表:5
回覆:8
積分:2
註冊:2009-03-21

發送簡訊給我
#10 引用回覆 回覆 發表時間:2009-03-30 21:29:40 IP:222.95.xxx.xxx 訂閱
delphi我是第一次用,第一次就要用来毕业设计....代码编的怪情有可原啦...
调试的时候会报错,运行工程文件也同样报错...
我在想是不是Delphi里通过ADO组件操作数据库不支持联合主键?...
我仔细看了下,我这个数据库表也没有设置联合主键的必要,所以把联合主键(p_id,r_id)取消掉了...
因为没主键,循环删除的时候会提示"键列信息不足"不能删...所以我在_P_R表里新增了一个递增字段作为主键...
对于delphi中这个联合主键问题我是绕过去了....因为老师在催,让我不要影响了进度...
我只是回避了这个联合主键的问题......以后有时间还是希望能弄清楚这个问题...
sidney_cn
一般會員


發表:1
回覆:4
積分:1
註冊:2009-06-26

發送簡訊給我
#11 引用回覆 回覆 發表時間:2009-07-24 09:42:48 IP:116.6.xxx.xxx 訂閱
  1. procedure TForm1.Button4Click(Sender: TObject);
  2. var
  3. r,p,i,j:integer;
  4. begin
  5. r :=strtoint(Edit1.Text);
  6. p :=strtoint(Edit2.Text);
  7. if (r<0) or (r>6) or (p<0) or (p>25) then
  8. begin
  9. showmessage('资源类数请限制在1-5之间;进程总数请限制在1-24之间');
  10. Edit1.Clear;
  11. Edit2.Clear;
  12. exit;
  13. end
  14. else
  15. begin
  16. rnum:=r;
  17. pnum:=p;
  18. ADOTable1.TableName:='_P_R';
  19. ADOTable1.Active:=True;
  20. for i:=1 to ADOTable1.RecordCount do
  21. begin
  22. ADOTable1.Delete;
  23. ADOTable1.Refresh;
  24. ADOTable1.next;
  25. end;
  26. for i:=1 to rnum do
  27. for j:=1 to pnum do
  28. begin
  29. ADOTable1.Insert;
  30. ADOTable1.FieldByName('p_id').AsInteger:=i;
  31. ADOTable1.FieldByName('r_id').AsInteger:=j;
  32. ADOTable1.Post;
  33. end
  34. end
  35. end;
条件判断时,没有考虑0的情况,即,当输入0时,也是可以过的。
if (not ((r>=1) and r<=5)) or (not ((p>=1) and (p<=25))) then
这样可读性是不是会好一些呢?


for i:=1 to ADOTable1.RecordCount do
begin
ADOTable1.Delete;
ADOTable1.Refresh;
.next;
end;

问题出在上面红色的位置,应该用一条ADOTable1.Delete就可以了,后面的两条就可以不用。
本来ADOTable1.Delete就已经做了下移的动作了,所以不用执行ADOTable1.Next

另外,是否可以用ADOQuery来执行删除的动作?
如:
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'delete _P_R';
ADOQuery1.Execute;

然后再用ADOTable1.Active打开

------
中国的软件,自己做
AndrewK
高階會員


發表:6
回覆:151
積分:161
註冊:2006-10-09

發送簡訊給我
#12 引用回覆 回覆 發表時間:2009-07-25 22:44:32 IP:115.43.xxx.xxx 訂閱
Hello

若要用 TAdotable 的 refresh 屬性功能
就把 TAdoTable 的CursorLocation 屬性
從 clUseClent 設成 clUseServer
(有得必有失)
可避免發生錯誤訊息

若想知道原因,可查看 TADOTable Refresh 的 Help
再查看 TADOTable CursorLocation 屬性的 Help
------
Just Do It
-------------------------
其實男生不是真的喜歡你不減肥,而是喜歡你愛吃還不肥;也不是真的喜歡你不化妝,而是喜歡你素顏也好看;也不是真的喜歡你瘦,而是喜歡你瘦卻有胸;也不是真喜歡你獨立,而是他忙的時候別煩他。女孩子,太認真你就輸了。
系統時間:2024-04-16 17:40:33
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!