Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 空数据库字段的数据类型是什么?_String_Delphi_Variables_Types_Null - Fatal编程技术网

String 空数据库字段的数据类型是什么?

String 空数据库字段的数据类型是什么?,string,delphi,variables,types,null,String,Delphi,Variables,Types,Null,我正在尝试为学校项目统计数据库中所有非空字段。请注意,我不允许使用SQL 这是代码 var i,k : Integer ; begin i := 0 ; with dmregisteredusers do begin tblusers.Sort := 'Nommer ASC'; tblusers.Edit; tblusers.First; For k:= 1 to tblusers.RecordCount do begin If

我正在尝试为学校项目统计数据库中所有非空字段。请注意,我不允许使用SQL

这是代码

var i,k : Integer ;
begin 
  i := 0 ;
  with dmregisteredusers do
  begin
    tblusers.Sort := 'Nommer ASC';
    tblusers.Edit;
    tblusers.First;
    For k:= 1 to tblusers.RecordCount do
    begin
      If (tblusers['Dogs wanted'] = '') OR (tblusers['Dogs wanted'] = ' ') 
        OR (tblusers['Dogswanted'] = 0) 
      then 
        tblusers.Next
      else 
      begin
        inc(i);
        tblusers.Next;
      end;//else
    end;//with
  end;//for
  ShowMessage('There are ' + IntToStr(i) + ' new dogs added to wishlist ,please contact the users regarding this matter and them remove the dogs from their wishlist !');
每次运行代码时,都会显示一个错误,即空的Db字段的数据类型为null


如何验证DB字段何时为空

这是您的代码的新版本。我做这件事的方式有点混乱,但我认为如果我在其中包含了对要点的评论和解释,这将是最容易理解的

首先要说的是,尽管检查给定行的dataset字段是否为Null并不是坏事,但如果不允许数据库在应用程序或原始Sql查询可能查询的列中存储Null,通常会更好。整本书的章节都是关于空值在理论和实践上的意义。在实践中,它们通常被认为只是“信息缺失”的意思。因此,我们无法在存在空值的情况下回答“该用户想要狗吗?”。因此,如何处理空值是一个策略和设计选择的问题,但是在数据库的实现中,通过对列施加NOTNULL约束来决定这个问题通常要好得多

当我在一篇评论中说Delphi并不擅长区分空字段和空字段时,我的意思是:对于字符串字段,对于字段为空的行,Delphi在调用field.AsString时返回空字符串“”。一些“纯粹主义者”会说,如果一个TField包含Null时被要求提供其AsXXX属性,它应该生成一个异常,因为它不应该试图“伪造”一个值,而事实上它没有。相反,它所做的是,返回一个空字符串,0代表一个数字字段等,这是一种务实的折衷:它避免了初学者被null的存在绊倒,但如果您希望代码处理null,可以使用TField.IsNull

如果你被一个包含DB的空缺所困扰,而且你会经常沮丧(除非你在DB的设计中有一个手)——考虑在SQL出现之前最好处理它们的可能性。 第二件事是,在没有明确的设计概要的情况下,我们并不真正知道“想要一只狗”的确切含义。例如,这是否意味着用户想要狗的单数、复数或是/否?Yes/No是最简单的处理方式,但并非所有数据库都支持显式布尔列类型,因此您经常会看到使用(希望是单个字符)CHAR、VARCHAR(或其Unicode等价物)列。或者一个整数列,如果要满足用户的挑剔要求

第三件事是,字段的Delphi数据类型不一定与db的列类型完全相同,尽管它们之间存在标准映射,但无论如何,通常最好在Delphi代码中使用值表示(例如,AsString、.AsInteger、.AsFloat等等)哪个最匹配db列类型

诚然,并不是所有的数据库实现都像Delphi处理列的数据类型那样挑剔,对不起,我的意思是小心,但大多数都是这样。一个值得注意的例外是Sqlite,虽然您可以在表的DDL中定义列类型,但Sqlite引擎更像是建议而不是规则,您可以在其中存储几乎任何内容

正如我在前面的评论中所说,Null是一个列/字段状态,而不是一个值。因此,询问“空DB字段的数据类型是什么?”是一种“类别错误”。列的数据类型是“它在tin上的确切含义”,即它在表的DDL中的定义。当然,您真正要问的是“如何确定字段是否为空”,这与Delphi编码一样,也是设计选择和db实现的问题

总之,不要再泛泛而谈了

procedure CountDogsWanted;
var
  // i,k : Integer ; <- names like i and k are usually as used for loop variables
  DogsWanted : Integer;
  Wanted : Boolean;
  S : String;  // contrast this naming style with what I said about the likes of i, j, k
    // I've done this because we might want to do several tests & operations on its value
    // and they will be easier to read with a shorter variable name.  Not such a good idea
    // when there are several such variables.
  AField : TField; 
const
  scDogsWanted = 'Dogs wanted';  // this is to avoid making mistakes with typos
begin

  {i := 0 ;}
  DogsWanted := 0;

  //  The point of the following line is to retrieve the field we're working with
  //  only once, rather than doing a FieldByName (which involves a serial iteration
  //  through the dataset's Fields collection) for each row in the dataset.
  //  The AField variable will remain valid for the duration of this procedure
  //  or until the dataset is closed if its Fields aren't defined as persistent ones.
  //  Persistent fields remain valid for the lifetime of their owners (usually a 
  // datamodule or form).  OTOH, "dynamic" fields are owned by the dataset and created
  // and destroyed when the dataset is opened and closed.  

  AField := dmregisteredusers.tblusers.FieldByName(scDogsWanted);

  {with dmregisteredusers do  <- Don't use "with", it only ever causes problems}
  {begin}

    {tblusers.Sort := 'Nommer ASC'; <- pointless, it makes no difference when you count what order the things are in}

    {tblusers.Edit; <- No! This puts the table into Edit state, but there's not point because you're not changing anything, and in any case, it will drop out of Edit state when you do a .Next}

    dmregisteredusers.tblusers.First;
    while not dmregisteredusers.tblusers.Eof do
    {For k:= 1 to tblusers.RecordCount do <- Never, ever, iterate a dataset with a For loop.
     The RecordCount is best avoided, too, because not all types of dataset return a meaningful
     RecordCount }

    begin
      //  You need to decide what to do about users whose 'Dogs wanted' field is Null
      //  If is is Null maybe we should ask for the record to be changed to indicate
      // explicitly whether a dog is wanted or not

      if AField.IsNull then begin
        // to be filled in by you
      end;
      //  You haven't told us what DataType the 'Dogs wanted' field is
      //  There are several possibilities.  For simplicity, let's assume that the DataType of the field is ftString
      //  Let's also make a design decision that *only* if the field only contains a 'Y' in upper or lower
      //  case, then that means a dog is wanted.
      //  First copy the field's string value into a local variable so we don't have to keep getting it for the
      //  following operation;
      S := dmregisteredusers.tblUsers.FieldByName(scDogsWanted).AsString;
      S := Trim(S);  { Trim() is a statndard function which removes leading and trailing whitespace }
      Wanted := CompareText(S, 'Y') = 0; { CompareText does a case-insensitive comparison and returns zero if equal}
      If
        { (tblusers['Dogs wanted'] = '') OR (tblusers['Dogs wanted'] = ' ')
          OR (tblusers['Dogswanted'] = 0)}
        Wanted
      then
        {tblusers.Next <- this is in the wrong place, you want to do a .Next regardless of the outcome of the "if"}
      else
      begin
        inc(DogsWanted);
        {tblusers.Next;}
      end;//else
      dmregisteredusers.tblusers.Next;
    {end;//with}
  end;//for
  ShowMessage('There are ' + IntToStr(DogsWanted) + ' new dogs added to wishlist ,please contact the users regarding this matter and them remove the dogs from their wishlist !')
end;
procedure CountDogsWanted;
变量

//i,k:整数 伙计们,我非常感谢你们在答案上的努力,我不能使用它们,因为我的导师知道这不是我自己的工作。。。 @MartynA你的编码回答了我的问题 这是新的编码 我知道它很草率,还有很多其他的方法可以工作,但我真的很紧迫,所以不能花时间学习代码…这里是我将使用的

For k:= 1 to tblusers.RecordCount do
begin
If dmregisteredusers.tblusers.FieldByName('Dogs wanted').IsNull then tblusers.Next
else
    begin
   inc(i) ;
   tblusers.Next;
   end//then begin

我使用了db form.onshow的排序,因此当DBGrid显示时,它的顺序是正确的…

您似乎缺少第三个“Dogs”之后的空格。打字错误无论如何,通过使用构造“tblusers['Dogs wanted']”,您正在访问字段的内容(如果有的话)作为变体(请参见OLH),我怀疑您目前有点太深了,无法理解当前任务会给您带来什么麻烦。使用tblusers.FieldByName(“想要的狗”)到达场地。它的DataType属性将告诉您它是什么类型。顺便说一句,不要使用“For”循环来迭代数据集。使用“whilenot tblusers.Eof do…”一词。而且,您使用的是什么数据库类型?此外,Delphi将数据集任何给定列的数据类型视为表中每一行的相同数据类型。Null不是一个值,而是一个状态,这意味着列(字段)没有相关行的值。无论是谁设置了您的项目,都应该解释这一点,以及空值为NULL的事实。这是一个重要的区别。如果中间名有一列,而您没有,那么该字段应该为空(“”)还是为空?德尔福实际上并不擅长尊重这种差异,但你需要弄清楚这一点。有趣的写作方式是:“希望列表,请”而不是“希望列表,请”。好的,单词和标点符号之间没有空格,但标点符号和下一个单词之间有一个空格。想想第二/第三个单词wrapOn发生了什么