精华内容
下载资源
问答
  • 在学习数据库记录集的属性与方法中,由RecordSource确定的具体可访问的数据构成的记录集Recordset也是一个对象,因而,它其他对象一样具有属性和方法。下面列出记录集常用的属性和方法。1.AbsolutePosition属性...

    学习数据库的记录集的属性与方法中,由RecordSource确定的具体可访问的数据构成的记录集Recordset也是一个对象,因而,它和其他对象一样具有属性和方法。下面列出记录集常用的属性和方法。

    1.AbsolutePosition属性

    AbsolutePosition返回当前指针值,如果是第1条记录,其值为0,该属性为只读属性。

    2.Bof和Eof的属性

    Bof判定记录指针是否在首记录之前,若Bof为True,则当前位置位于记录集的第1条记录之前。与此类似,Eof判定记录指针是否在末记录之后。

    3.Bookmark属性

    Bookmark属性的值采用字符串类型,用于设置或返回当前指针的标签。在程序中可以使用Bookmark属性重定位记录集的指针,但不能使用AbsolutePostion属性。

    4.Nomatch属性

    在记录集中进行查找时,如果找到相匹配的记录,则Recordset的NoMatch属性为False,否则为True。该属性常与Bookmark属性一起使用。

    5.RecordCount属性

    RecordCount属性对Recordset对象中的记录计数,该属性为只读属性。在多用户环境下,RecordCount属性值可能不准确,为了获得准确值,在读取RecordCount属性值之前,可使用MoveLast方法将记录指针移至最后一条记录上。

    6.Move方法

    使用Move方法可代替对数据控件对象的4个箭头按钮的操作遍历整个记录集。5种Move方法是:

    (1)MoveFirst方法:移至第1条记录。

    (2)MoveLast方法:移至最后一条记录。

    (3)MoveNext方法:移至下一条记录。

    (4)MovePrevious方法:移至上一条记录。

    (5)Move [n] 方法:向前或向后移n条记录,n为指定的数值。

    在窗体上用4个命令按钮代替例9.2数据控件对象的4个箭头按钮的操作。窗体上增加4个命令按钮,将数据控件的Visible属性设置为False,通过对4个命令按钮的编程代替对数据控件对象的4个箭头按钮的操作。

    命令按钮Command1­_Click事件移至第1条记录,代码如下:

    Private Sub Command1_Click()

    Data1.Recordset.MoveFirst

    End Sub

    命令按钮Command4_Click事件移至最后一条记录,代码如下:

    Private Sub Command4_Click()

    Data1.Recordset.MoveLast

    End Sub

    另外两个按钮的代码需要考虑Recordset对象的边界的首尾,如果越界,则用MoveFirst方法定位到第1条记录或用MoveLast方法定位到最后一条记录。程序代码如下:

    Private Sub Command2_Click()

    Data1.Recordset.MovePrevious

    If Data1.Recordset.BOF Then Data1.Recordset.MoveFirst

    End Sub

    Private Sub Command3_Click()

    Data1.Recordset.MoveNext

    If Data1.Recordset.EOF Then Data1.Recordset.MoveLast

    End Sub

    7.Find方法

    使用Find方法可在指定的Dynaset或Snapshot类型的Recordset对象中查找与指定条件相符的一条记录,并使之成为当前记录。4种Find方法是:

    (1)FindFirst方法:从记录集的开始查找满足条件的第1条记录。

    (2)FindLast方法:从记录集的尾部向前查找满足条件的第l条记录。

    (3)FindNext方法:从当前记录开始查找满足条件的下一条记录。

    (4)FindPrevious方法:从当前记录开始查找满足条件的上一条记录。

    4种Find方法的语法格式相同:

    数据集合.Find方法条件

    搜索条件是一个指定字段与常量关系的字符串表达式。在构造表达式时,除了用普通的关系运算外,还可以用Like运算符。

    例如:语句 “Data1.Recordset.FindFirst专业=’物理’”表示在由Data1数据控件所连接的数据库Student.mdb的记录集内查找专业为“物理”的第l条记录。这里,“专业”为数据库Student记录集中的字段名,在该字段中存放专业名称信息。要想查找下一条符合条件的记录,可继续使用语句:”Data1.Recordset.FindNext专业=’物理’”。

    又例如:与c#数据库编程相似的要在记录集内查找专业名称中带有“建”字的专业:

    Data1.Recordset.FindFirst 专业 Like ”*建*”

    字符串“*建*”匹配字段专业中带有“建”字字样的所有专业名称字符串。

    需要指出的是Find方法在找不到相匹配的记录时,当前记录保持在查找的始发处,NoMatch属性为True。如果Find方法找到相匹配的记录,则记录定位到该记录,Recordset的NoMatch属性为False。

    8.Seek方法

    使用Seek方法必须打开表的索引,它在Table表中查找与指定索引规则相符的第1条记录,并使之成为当前记录。其语法格式为:

    数据表对象.seek comparison,keyl,key2…

    Seek允许接受多个参数,第1个是比较运算符comparison,Seek方法中可用的比较运算符有=、>=、>、<>、<、<=等。

    在使用Seek方法定位记录时,必须通过Index属性设置索引。若在记录集中多次使用同样的Seek方法(参数相同),那么找到的总是同一条记录。

    例如:假设数据库Student内基本情况表的索引字段为学号,满足学号字段值大于等于110001的第1条记录可使用以下程序代码:

    Data1.RecordsetType = 0’设置记录集类型为Table

    Data1.RecordSource = "基本情况"’打开基本情况表单

    Data1.Refresh

    Data1.Recordset.Index = "jbqk_no"’打开名称为jbqk_no的索引

     

    转载于:https://blog.51cto.com/hudongwang2013/1265356

    展开全文
  • 这几天学习PHP,感觉自己的编程...数据库值属性的查询,可以把数据库取出来的放到数组里面,然后再通过数组取出。 +-----------+--------+ | user_name | passwd | +-----------+--------+ | 生 | 123 |...

    这几天学习PHP,感觉自己的编程能力还是太弱了,这里记录一下自己遇到的问题和网上搜索找到的解决办法。

    数据库多值属性的查询,可以把数据库取出来的值放到数组里面,然后再通过数组取出。

     

    +-----------+--------+

    | user_name | passwd |

    +-----------+--------+

    | 生        | 123    |

    | 能看      | 123    |

    | 糊涂      | 123    |

    这还不算是个多值属性的表,但是就拿来当个简单的例子吧。
     
     
    1. $result = mysql_query("SELECT user_name, passwd FROM user"); 
    2. $arr0 = array(); 
    3. while($row = mysql_fetch_array($result)) 
    4.     { 
    5.     // echo $row[0]; 
    6.     $arr = array
    7.             $row['user_name'],$row['passwd']     
    8.     ); 
    9.     array_push($arr0$arr);  
    10.      } 
    11.       print_r($arr0[0][0]); //这就能显示“生”同理,取出“糊涂”那就是$arr0[1][0] 
    12.   
     
     
     
    (2)数据库取出的值怎么放到写好的HTML中。
    方法可能也是比较笨的,刚开始学,好的方法求共享。
     首先:
    $sql="select * from 表名 where 条件;
        $rs=mysql_query($sql); 
        while($row=mysql_fetch_array($rs))
       
        $name=$row['字段']; //这样就取出了这个值了
             }
     
    然后使用JS传值
     
    1.  <script language="javascript">  
    2.     var  name="<?php echo $name;?>";   //上面的值转换为js变量 
    3.     function name_onclick() 
    4.    {  
    5.         frm=document.my_message;    //my_message是表单名字 
    6.         frm.name.value=name;     //name是id号 
    7.    } 
    8.     name_onclick(); 
    9. </script>  
     

     

    转载于:https://blog.51cto.com/zgssheng/937770

    展开全文
  • EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态 原文:EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态本文目录 查看实体当前...
    原文:EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态

    本文目录

    文章开始前建议大家为了更好的记忆最好自己实现文中的所有方法。如果非要直接运行我的demo,必要的时候需要恢复下数据库数据,否则找不到记录。

    之前的章节已经演示了context.Entry方法可以拿到实体的状态(EntityState),来看一个方法:

            /// <summary>
            /// 单个实体的状态
            /// </summary>
            private static void PrintState()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var canyon = (from d in context.Destinations
                                  where d.Name == "Grand Canyon"
                                  select d).Single();
                    DbEntityEntry<DbContexts.Model.Destination> entry = context.Entry(canyon);
                    Console.WriteLine("Before Edit:{0}", entry.State);   //Unchaged
    
                    canyon.TravelWarnings = "Take a lot of Water!";
                    DbEntityEntry<DbContexts.Model.Destination> entrys = context.Entry(canyon);
    
    Console.WriteLine(
    "After Edit:{0}", entrys.State); //Modified } }

    context.Entry方法有两个重载,分别返回泛型DbEntityEntry<TEntity>和非泛型的DbEntityEntry,它们都可以监测到实体的状态,并且通过DbEntityEntry还可以操作实体的当前值、原始值和数据库值。分别是:

    • 当前值(Current Value):程序里设置实体属性的值(在内存中,还没提交数据库);
    • 原始值(Original Value):被数据库上下文跟踪到时的值(程序取出数据库的值,可能不是最新的);
    • 数据库值(Database Value):数据库里的值(此时此刻数据库里最新的值)

    来看一个例子:

            /// <summary>
            /// 打印实体当前、原始和数据库值
            /// </summary>
            private static void PrintLodgingInfo()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var hotel = (from d in context.Lodgings
                                 where d.Name == "Grand Hotel"
                                 select d).Single();
                    hotel.Name = "Super Grand Hotel";
                    context.Database.ExecuteSqlCommand(@"UPDATE Lodgings SET Name = 'Not-So-Grand Hotel' WHERE Name = 'Grand Hotel'");
                    PrintChangeTrackingInfo(context, hotel);
                }
            }
            private static void PrintChangeTrackingInfo(DbContexts.DataAccess.BreakAwayContext context, DbContexts.Model.Lodging entity)
            {
                var entry = context.Entry(entity);
                Console.WriteLine(entry.Entity.Name);
                Console.WriteLine("State: {0}", entry.State);
    
                Console.WriteLine("\nCurrent Values:");
                PrintPropertyValues(entry.CurrentValues);
    
                Console.WriteLine("\nOriginal Values:");
                PrintPropertyValues(entry.OriginalValues);
    
                Console.WriteLine("\nDatabase Values:");
                PrintPropertyValues(entry.GetDatabaseValues());
            }
            private static void PrintPropertyValues(DbPropertyValues values)
            {
                foreach (var propertyName in values.PropertyNames)
                {
                    Console.WriteLine(" - {0}: {1}", propertyName, values[propertyName]);
                }
            }

    方法分析:先从数据库取出一个实体,然后修改其Name属性,这个时候当前值(Current)和原始值(Original)都有了,分别是:修改后的值(还没提交,在内存中)和从库里取出来时实体的值。再使用Database.ExecuteSqlCommand执行了一段修改此对象在数据库中的值,这个时候数据库值(Database)也有了变化,这个实体的三个值都不相同了。还没看到打印结果,在执行entry.GetDatabaseValues()方法时报了一个EntitySqlException错:

    找不到类型DbContexts.DataAccess.Lodging,项目的Lodging实体明明在DbContexts.Model.Lodging命名空间下,反复检查代码没发现任何问题,报这个错真是很疑惑。最后通过搜索引擎才知道这是EF4.1/4.2版本的一个bug,解决办法:修改实体和上下文到一个命名空间,或者使用EF4.3 release。看看本书作者Julie Lerman在msdn论坛上关于此bug的回复

    换成4.3版本的EF问题就立马解决了(源码的libs目录下提供了EF4.3)。看下打印的结果:

    结果分析:当前值为方法里修改的值、原始值是从数据库取出未做任何操作的值、数据库值是此时数据库里的值。当然新添加的实体不会有原始值和数据库值、删除的实体也不会有当前值,利用EntityState完善下方法:

            private static void PrintChangeTrackingInfo(DbContexts.DataAccess.BreakAwayContext context, DbContexts.Model.Lodging entity)
            {
                var entry = context.Entry(entity);
                Console.WriteLine(entry.Entity.Name);
                Console.WriteLine("State: {0}", entry.State);
    
                if (entry.State != EntityState.Deleted)   //标记删除的实体不会有当前值
                {
                    Console.WriteLine("\nCurrent Values:");
                    PrintPropertyValues(entry.CurrentValues);
                }
                if (entry.State != EntityState.Added)   //新添加的时候不会有原始值和数据库值
                {
                    Console.WriteLine("\nOriginal Values:");
                    PrintPropertyValues(entry.OriginalValues);
                    Console.WriteLine("\nDatabase Values:");
                    PrintPropertyValues(entry.GetDatabaseValues());
                }
            }

    为了测试重写下PrintLodgingInfo方法:

            /// <summary>
            /// 测试打印添加和删除时实体当前、原始和数据库值
            /// </summary>
            private static void PrintLodgingInfoAddAndDelete()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var hotel = (from d in context.Lodgings
                                 where d.Name == "Grand Hotel"
                                 select d).Single();
                    PrintChangeTrackingInfo(context, hotel);   //默认
    
                    var davesDump = (from d in context.Lodgings
                                     where d.Name == "Dave's Dump"
                                     select d).Single();
                    context.Lodgings.Remove(davesDump);
                    PrintChangeTrackingInfo(context, davesDump);   //测试删除实体
    
                    var newMotel = new DbContexts.Model.Lodging { Name = "New Motel" };
                    context.Lodgings.Add(newMotel);
                    PrintChangeTrackingInfo(context, newMotel);  //测试新添加实体
                }
            }

    当然上面打印实体类型的方法并不通用,修改第二个参数为object类型:

            /// <summary>
            /// 通用的打印实体方法
            /// </summary>
            private static void PrintChangeTrackingInfo(DbContexts.DataAccess.BreakAwayContext context, object entity)
            {
                var entry = context.Entry(entity);
                Console.WriteLine("Type:{0}", entry.Entity.GetType());   //打印实体类型
                Console.WriteLine("State: {0}", entry.State);
    
                if (entry.State != EntityState.Deleted)   //标记删除的实体不会有当前值
                {
                    Console.WriteLine("\nCurrent Values:");
                    PrintPropertyValues(entry.CurrentValues);
                }
                if (entry.State != EntityState.Added)   //新添加的时候不会有原始值和数据库值
                {
                    Console.WriteLine("\nOriginal Values:");
                    PrintPropertyValues(entry.OriginalValues);
                    Console.WriteLine("\nDatabase Values:");
                    PrintPropertyValues(entry.GetDatabaseValues());
                }
            }

    看看打印结果:

    之前打印实体的各种属性都是通过遍历的形式(PrintPropertyValues方法)打印出来,如果仅取某个字段当然没必要这么麻烦,可以使用GetValue<TValue>:

            /// <summary>
            /// 打印实体单个属性
            /// </summary>
            private static void PrintOriginalName()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var hotel = (from d in context.Lodgings
                                 where d.Name == "Grand Hotel"
                                 select d).Single();
                    hotel.Name = "Super Grand Hotel";
                    string originalName = context.Entry(hotel).OriginalValues.GetValue<string>("Name");
    
                    Console.WriteLine("Current Name: {0}", hotel.Name);  //Super Grand Hotel
                    Console.WriteLine("Original Name: {0}", originalName);  //Grand Hotel
                }
            }

    拷贝DbPropertyValues到实体:ToObject方法

            /// <summary>
            /// 拷贝DbPropertyValues到实体:ToObject方法
            /// </summary>
            private static void TestPrintDestination()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var reef = (from d in context.Destinations
                                where d.Name == "Great Barrier Reef"
                                select d).Single();
                    reef.TravelWarnings = "Watch out for sharks!";
                    Console.WriteLine("Current Values");
                    PrintDestination(reef);
    
                    Console.WriteLine("\nDatabase Values");
                    DbPropertyValues dbValues = context.Entry(reef).GetDatabaseValues();
                    PrintDestination((DbContexts.Model.Destination)dbValues.ToObject());  //ToObject方法创建Destination实例
                }
            }
            private static void PrintDestination(DbContexts.Model.Destination destination)
            {
                Console.WriteLine("-- {0}, {1} --", destination.Name, destination.Country);
                Console.WriteLine(destination.Description);
                if (destination.TravelWarnings != null)
                {
                    Console.WriteLine("WARNINGS!: {0}", destination.TravelWarnings);
                }
            }

    方法分析:从Destination表里取出Name为Great Barrier Reef的实体并修改其TravelWarnings字段,然后调用PrintDestination方法打印当前实体的各属性,再查出此实体在数据库里的值,并且通过ToObject方法把数据库取出来的这个对象也转换成了实体对象。这么转有什么好处呢?这个通过ToObject转换的Destination实例不会被数据库上下文追踪,所以对其做的任何改变都不会提交数据库。看看打印结果:

    修改DbPropertyValues当前值:

    调用上下文的Entry方法,传入要操作的实体对象,再打点就可以拿到实体的当前值(CurrentValues)、原始值(OriginalValues)、数据库值(GetDatabaseValues()),返回类型是DbPropertyValues,直接遍历就可以输出实体的所有属性。当然DbPropertyValues并不是只读的。写个方法修改试试:

            /// <summary>
            /// 修改DbPropertyValues当前值
            /// </summary>
            private static void ChangeCurrentValue()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var hotel = (from d in context.Lodgings
                                 where d.Name == "Grand Hotel"
                                 select d).Single();
                    context.Entry(hotel).CurrentValues["Name"] = "Hotel Pretentious";
                    Console.WriteLine("Property Value: {0}", hotel.Name);
                    Console.WriteLine("State: {0}", context.Entry(hotel).State);  //Modified
                }
            }

    类似于索引器的方式赋值即可,赋值后实体的状态已经是Modified了,显然已经被上下文追踪到了,这个时候调用上下文的SaveChanges方法将会提交到数据库。那么如果只是想打印和修改实体状态以供查看,并不像被提交到数据库怎么办?


    最好的办法就是克隆,先克隆实体然后操作克隆之后的实体:

            /// <summary>
            /// 克隆实体:Clone
            /// </summary>
            private static void CloneCurrentValues()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var hotel = (from d in context.Lodgings
                                 where d.Name == "Grand Hotel"
                                 select d).Single();
                    var values = context.Entry(hotel).CurrentValues.Clone();  //Clone方法
                    values["Name"] = "Simple Hotel";
                    Console.WriteLine("Property Value: {0}", hotel.Name);
                    Console.WriteLine("State: {0}", context.Entry(hotel).State);  //Unchanged
                }
            }

    设置实体的值:SetValues方法

    当然实体的当前值、原始值和数据库值都是可以相互复制的:

            /// <summary>
            /// 设置实体的值:SetValues方法
            /// </summary>
            private static void UndoEdits()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var canyon = (from d in context.Destinations
                                  where d.Name == "Grand Canyon"
                                  select d).Single();
                    canyon.Name = "Bigger & Better Canyon";
    
                    var entry = context.Entry(canyon);
                    entry.CurrentValues.SetValues(entry.OriginalValues);
                    entry.State = EntityState.Unchanged;  //标记未修改
    
                    Console.WriteLine("Name: {0}", canyon.Name); //Grand Canyon
                }
            }

    上面的方法演示了拷贝原始值到当前值,最终保存的是当前值。很方便,不需要挨个赋值。

    再看看如何使用SetValues方法实现之前说的克隆实体:

            /// <summary>
            /// 克隆实体:SetValues
            /// </summary>
            private static void CreateDavesCampsite()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var davesDump = (from d in context.Lodgings
                                     where d.Name == "Dave's Dump"
                                     select d).Single();
                    var clone = new DbContexts.Model.Lodging();
                    context.Lodgings.Add(clone);
    
                    context.Entry(clone).CurrentValues.SetValues(davesDump);  //克隆davesDump的值到新对象clone里
                    clone.Name = "Dave's Camp";  //修改Name属性
                    context.SaveChanges();  //最后提交修改
    
                    Console.WriteLine("Name: {0}", clone.Name);  //Dave's Camp
                    Console.WriteLine("Miles: {0}", clone.MilesFromNearestAirport);  //32.65
                    Console.WriteLine("Contact Id: {0}", clone.PrimaryContactId);  //1
                }
            }
    exec sp_executesql N'insert [dbo].[Lodgings]([Name], [Owner], [MilesFromNearestAirport], [destination_id], [PrimaryContactId], [SecondaryContactId], [Entertainment], [Activities], [MaxPersonsPerRoom], [PrivateRoomsAvailable], [Discriminator])
    values (@0, null, @1, @2, @3, null, null, null, null, null, @4)
    select [LodgingId]
    from [dbo].[Lodgings]
    where @@ROWCOUNT > 0 and [LodgingId] = scope_identity()',N'@0 nvarchar(200),@1 decimal(18,2),@2 int,@3 int,@4 nvarchar(128)',@0=N'Dave''s Camp',@1=32.65,@2=1,@3=1,@4=N'Lodging'

    很明显实体已经被克隆了。

    获取和设置实体的单个属性:Property方法

            /// <summary>
            /// 获取和设置实体的单个属性:Property方法
            /// </summary>
            private static void WorkingWithPropertyMethod()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var davesDump = (from d in context.Lodgings
                                     where d.Name == "Dave's Dump"
                                     select d).Single();
                    var entry = context.Entry(davesDump);
                    entry.Property(d => d.Name).CurrentValue = "Dave's Bargain Bungalows";  //设置Name属性
    
                    Console.WriteLine("Current Value: {0}", entry.Property(d => d.Name).CurrentValue);  //Dave's Bargain Bungalows
                    Console.WriteLine("Original Value: {0}", entry.Property(d => d.Name).OriginalValue);  //Dave's Dump
                    Console.WriteLine("Modified?: {0}", entry.Property(d => d.Name).IsModified);   //True
                }
            }

    同样可以查询出实体的哪些属性被修改了:IsModified方法

            /// <summary>
            /// 查询实体被修改字段:IsModified方法
            /// </summary>
            private static void FindModifiedProperties()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var canyon = (from d in context.Destinations
                                  where d.Name == "Grand Canyon"
                                  select d).Single();
                    canyon.Name = "Super-Size Canyon";
                    canyon.TravelWarnings = "Bigger than your brain can handle!!!";
                    var entry = context.Entry(canyon);
                    var propertyNames = entry.CurrentValues.PropertyNames;  //获取所有的Name列
    
                    IEnumerable<string> modifiedProperties = from name in propertyNames
                                                             where entry.Property(name).IsModified
                                                             select name;
                    foreach (var propertyName in modifiedProperties)
                    {
                        Console.WriteLine(propertyName);  //Name、TravelWarnings
                    }
                }
            }

    前面的章节已经讲解了如何查询一对一、一对多等关系的导航属性了,还不了解的点这里。现在讲讲如何修改导航属性:

            /// <summary>
            /// 修改导航属性(Reference):CurrentValue方法
            /// </summary>
            private static void WorkingWithReferenceMethod()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var davesDump = (from d in context.Lodgings
                                     where d.Name == "Dave's Dump"
                                     select d).Single();
                    var entry = context.Entry(davesDump);
                    entry.Reference(l => l.Destination).Load();   //显示加载
    
                    var canyon = davesDump.Destination;
                    Console.WriteLine("Current Value After Load: {0}", entry.Reference(d => d.Destination).CurrentValue.Name);
    
                    var reef = (from d in context.Destinations
                                where d.Name == "Great Barrier Reef"
                                select d).Single();
                    entry.Reference(d => d.Destination).CurrentValue = reef;   //修改
                    Console.WriteLine("Current Value After Change: {0}", davesDump.Destination.Name);
                }
            }

    打印结果:
    Current Value After Load: Grand Canyon
    Current Value After Change: Great Barrier Reef

    注:上面的方法并没有调用上下文的SaveChanges方法,故程序跑完数据也不会保存到数据库,本文所有方法仅作演示都未提交数据库。

    有Reference找单个属性的,那么自然也有Collection找集合属性的:

            /// <summary>
            /// 修改导航属性(Collection):CurrentValue方法
            /// </summary>
            private static void WorkingWithCollectionMethod()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var res = (from r in context.Reservations
                               where r.Trip.Description == "Trip from the database"
                               select r).Single();
                    var entry = context.Entry(res);
                    entry.Collection(r => r.Payments).Load();
                    Console.WriteLine("Payments Before Add: {0}", entry.Collection(r => r.Payments).CurrentValue.Count);
    
                    var payment = new DbContexts.Model.Payment { Amount = 245 };
                    context.Payments.Add(payment);
                    entry.Collection(r => r.Payments).CurrentValue.Add(payment);  //修改
                    Console.WriteLine("Payments After Add: {0}", entry.Collection(r => r.Payments).CurrentValue.Count);
                }
            }

    打印结果:
    Payments Before Add: 1
    Payments After Add: 2

    从数据库取出实体加载到内存中,可能并不立马就展示给用户看。在进行一系列的排序、筛选等操作再展示出来。但是怎么确定展示的时候这些实体没有被修改过呢?可以使用Reload方法重新加载:

            /// <summary>
            /// 取当前最新的数据库值:Reload方法
            /// </summary>
            private static void ReloadLodging()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var hotel = (from d in context.Lodgings
                                 where d.Name == "Grand Hotel"
                                 select d).Single();  //取出实体
                    context.Database.ExecuteSqlCommand(@"UPDATE dbo.Lodgings SET Name = 'Le Grand Hotel' WHERE Name = 'Grand Hotel'");   //立马修改实体值(这个时候数据库中的值已改变,但是取出来放在内存中的值并没改变)
                    Console.WriteLine("Name Before Reload: {0}", hotel.Name);
                    Console.WriteLine("State Before Reload: {0}", context.Entry(hotel).State);
    
                    context.Entry(hotel).Reload();
                    Console.WriteLine("Name After Reload: {0}", hotel.Name);
                    Console.WriteLine("State After Reload: {0}", context.Entry(hotel).State);
                }
            }

    打印结果:
    Name Before Reload: Grand Hotel
    State Before Reload: Unchanged
    Name After Reload: Le Grand Hotel
    State After Reload: Unchanged

    可以看出Reload方法已经重新取出了数据库中的最新值。来看看Reload方法生成的sql:

    SELECT 
    [Extent1].[Discriminator] AS [Discriminator], 
    [Extent1].[LodgingId] AS [LodgingId], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Owner] AS [Owner], 
    [Extent1].[MilesFromNearestAirport] AS [MilesFromNearestAirport], 
    [Extent1].[destination_id] AS [destination_id], 
    [Extent1].[PrimaryContactId] AS [PrimaryContactId], 
    [Extent1].[SecondaryContactId] AS [SecondaryContactId], 
    [Extent1].[Entertainment] AS [Entertainment], 
    [Extent1].[Activities] AS [Activities], 
    [Extent1].[MaxPersonsPerRoom] AS [MaxPersonsPerRoom], 
    [Extent1].[PrivateRoomsAvailable] AS [PrivateRoomsAvailable]
    FROM [dbo].[Lodgings] AS [Extent1]
    WHERE ([Extent1].[Discriminator] IN ('Resort','Hostel','Lodging')) AND ([Extent1].[LodgingId] = 1)

    当然Reload方法也会保存内存中修改的数据,这个并不会冲突。在方法里的linq查询后面加上:hotel.Name = "A New Name"; 打印结果就是这样的了:
    Name Before Reload: A New Name
    State Before Reload: Modified
    Name After Reload: Le Grand Hotel
    State After Reload: Unchanged

    注意,代码里修改的Name已经显示了,并且标记实体状态为Modified了,Modified会在调用上下文的SaveChanges方法的时候提交到数据库。这个过程是这样的:

    加载实体到内存中 - 在内存中对实体的某个属性进行修改 - 使用ExecuteSqlCommand方法执行sql修改数据库里该实体的值 - 调用Reload取出数据库里本实体的最新值 - 调用SaveChanges方法的话,在内存中对实体的修改也会被提交到数据库

    之前操作了单个实体,现在看看如何读取关联实体和状态。使用DbContext.ChangeTracker.Entries方法:

         /// <summary>
            /// 读取相关联的实体和状态:DbContext.ChangeTracker.Entries方法
            /// </summary>
            private static void PrintChangeTrackerEntries()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var res = (from r in context.Reservations
                               where r.Trip.Description == "Trip from the database"
                               select r).Single();
                    context.Entry(res).Collection(r => r.Payments).Load();
    res.Payments.Add(
    new DbContexts.Model.Payment { Amount = 245 }); var entries = context.ChangeTracker.Entries(); foreach (var entry in entries) { Console.WriteLine("Entity Type: {0}", entry.Entity.GetType()); Console.WriteLine(" - State: {0}", entry.State); } } }

    添加了一个从表实体,并读取所有关联实体和其状态,打印结果:
    Entity Type: DbContexts.Model.Payment - State: Added
    Entity Type: DbContexts.Model.Reservation - State: Unchanged
    Entity Type: DbContexts.Model.Payment - State: Unchanged

    EF里如何解决更新数据时的冲突

    正常根据实体的主键修改实体的时候,EF是不会判断数据修改之前有没有被别的人修改过,但是如果做了并发控制,EF在更新某条记录的时候才会抛错。这个系列文章的demo里有两个实体做了并发控制:Person类的SocialSecurityNumber字段被标记了ConcurrencyCheck;Trip类的RowVersion字段被标记了Timestamp。来写一个触发DbUpdateConcurrencyException异常的方法并处理这个异常:

            /// <summary>
            /// 修改实体
            /// </summary>
            private static void ConcurrencyDemo()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var trip = (from t in context.Trip.Include(t => t.Destination)
                                where t.Description == "Trip from the database"
                                select t).Single();
                    trip.Description = "Getaway in Vermont";
                    context.Database.ExecuteSqlCommand(@"UPDATE dbo.Trips SET CostUSD = 400 WHERE Description = 'Trip from the database'");
                    SaveWithConcurrencyResolution(context);
                }
            }
            /// <summary>
            /// 尝试保存
            /// </summary>
            private static void SaveWithConcurrencyResolution(DbContexts.DataAccess.BreakAwayContext context)
            {
                try
                {
                    context.SaveChanges();
                }
                catch (DbUpdateConcurrencyException ex)
                {
                    ResolveConcurrencyConflicts(ex);
                    SaveWithConcurrencyResolution(context);
                }
            }

    方法分析:取出实体 - 修改实体Description属性(此时实体状态为Modified)- 使用ExecuteSqlCommand执行sql修改了CostUSD和Description字段(修改后时间戳已经不同了,PS:使用ExecuteSqlCommand执行sql不需要调用SaveChanges方法)- 调用上下文的SaveChanges方法保存之前被标记为Modified的实体,这个时候就会报一个DbUpdateConcurrencyException的异常,因为时间戳列已经找不到了,这个更新的where条件根本找不到记录了。有时间戳的列更新都是双条件,时间戳详细用法点这里了解。

    尝试写个方法解决这个冲突:

            /// <summary>
            /// 解决冲突
            /// </summary>
            private static void ResolveConcurrencyConflicts(DbUpdateConcurrencyException ex)
            {
                foreach (var entry in ex.Entries)
                {
                    Console.WriteLine("Concurrency conflict found for {0}", entry.Entity.GetType());
    
                    Console.WriteLine("\nYou are trying to save the following values:");
                    PrintPropertyValues(entry.CurrentValues);  //用户修改的值
    
                    Console.WriteLine("\nThe values before you started editing were:");
                    PrintPropertyValues(entry.OriginalValues);  //从库里取出来时的值
    
                    var databaseValues = entry.GetDatabaseValues();  //即时数据库的值
                    Console.WriteLine("\nAnother user has saved the following values:");
                    PrintPropertyValues(databaseValues);
    
                    Console.WriteLine("[S]ave your values, [D]iscard you changes or [M]erge?");
                    var action = Console.ReadKey().KeyChar.ToString().ToUpper(); //读取用户输入的字母
                    switch (action)
                    {
                        case "S":
                            entry.OriginalValues.SetValues(databaseValues);  //拷贝数据库值到当前值(恢复时间戳)
                            break;
                        case "D":
                            entry.Reload();  //重新加载
                            break;
                        case "M":
                            var mergedValues = MergeValues(entry.OriginalValues, entry.CurrentValues, databaseValues);//合并
                            entry.OriginalValues.SetValues(databaseValues);  //拷贝数据库值到当前值(恢复时间戳)
                            entry.CurrentValues.SetValues(mergedValues);     //拷贝合并后的值到当前值,最终保存的是当前值
                            break;
                        default:
                            throw new ArgumentException("Invalid option");
                    }
                }
            }

    捕获到异常后告知用户要修改实体的原始值(用户修改前从数据库取出来的值)、现在的值(用户修改的值)、数据库里的值(此时数据库里的值,这个值已被修改,不是用户修改前取出来的值了),打印出来的结果显示已经有人修改了这条记录了。最后是问用户是否保存修改。分别是保存、放弃、合并修改。

    用户输入"S"表示“保存”,case语句块里执行的操作是拷贝数据库值到原始值,这里该有疑惑了,调用SaveChanges方法保存的也是currentValues当前值,跟databaseValues数据库值还有OriginalValues原始值没有任何关系啊。其实这么操作是恢复一下时间戳的值方便更新,之前说过timestamp的列更新条件是两个,任何一个不对都更新不了。看看sql:

    exec sp_executesql N'update [dbo].[Trips]
    set [Description] = @0, [CostUSD] = @1
    where (([Identifier] = @2) and ([RowVersion] = @3))
    select [RowVersion]
    from [dbo].[Trips]
    where @@ROWCOUNT > 0 and [Identifier] = @2',N'@0 nvarchar(max) ,@1 decimal(18,2),@2 uniqueidentifier,@3 binary(8)',@0=N'Getaway in Vermont',@1=1000.00,@2='CF2E6BD3-7393-440C-941A-
    9124C61CE04A',@3=0x00000000000007D2

    结果只保存了自己的修改:

    用户输入“D”表示“放弃”,case语句块里执行的是Reload方法,这个方法之前已经介绍过了,是重新加载数据库里的最新值(Latest Value)。恢复下数据库数据再执行下方法,看看sql:

    SELECT 
    [Extent1].[Identifier] AS [Identifier], 
    [Extent1].[StartDate] AS [StartDate], 
    [Extent1].[EndDate] AS [EndDate], 
    [Extent1].[Description] AS [Description], 
    [Extent1].[CostUSD] AS [CostUSD], 
    [Extent1].[RowVersion] AS [RowVersion], 
    [Extent1].[DestinationId] AS [DestinationId]
    FROM [dbo].[Trips] AS [Extent1]
    WHERE [Extent1].[Identifier] = cast('cf2e6bd3-7393-440c-941a-9124c61ce04a' as uniqueidentifier)

    取了下数据库里该实体最新的值(使用ExecuteSqlCommand更新后的值),没有其他任何更新语句,就是放弃本次修改的意思,但是之前ExecuteSqlCommand方法执行的修改是有效的,看看结果:

    上面的“保存修改”和“放弃修改”只能保存一个,如果让用户修改的和ExecuteSqlCommand的修改同时生效呢,选择M,意为合并。看看合并方法:

            /// <summary>
            /// 合并
            /// </summary>
            private static DbPropertyValues MergeValues(DbPropertyValues original, DbPropertyValues current, DbPropertyValues database)
            {
                var result = original.Clone();  //拷贝原始值并存放合并后的值
                foreach (var propertyName in original.PropertyNames)  //遍历原始值的所有列
                {
                    if (original[propertyName] is DbPropertyValues)  //判断当前列是否复杂类型(很少)
                    {
                        var mergedComplexValues =
                            MergeValues((DbPropertyValues)original[propertyName],
                            (DbPropertyValues)current[propertyName],
                            (DbPropertyValues)database[propertyName]);   //是复杂类型的话就使用递归合并复杂类型的值
                        ((DbPropertyValues)result[propertyName]).SetValues(mergedComplexValues);
                    }
                    else  //是普通里的话就和当前值、数据库值、原始值各种对比。修改了就赋值
                    {
                        if (!object.Equals(current[propertyName], original[propertyName]))
                            result[propertyName] = current[propertyName];
                        else if (!object.Equals(database[propertyName], original[propertyName]))
                            result[propertyName] = database[propertyName];
                    }
                }
                return result;
            }

    看看sql:

    exec sp_executesql N'update [dbo].[Trips]
    set [Description] = @0, [CostUSD] = @1
    where (([Identifier] = @2) and ([RowVersion] = @3))
    select [RowVersion]
    from [dbo].[Trips]
    where @@ROWCOUNT > 0 and [Identifier] = @2',N'@0 nvarchar(max) ,@1 decimal(18,2),@2 uniqueidentifier,@3 binary(8)',@0=N'Getaway in Vermont',@1=400.00,@2='CF2E6BD3-7393-440C-941A-9124C61CE04A',@3=0x00000000000007DC

    看看结果:

    用户修改和ExecuteSqlCommand修改的都保存上了。

    最后讲一个更实用的东西:重写上下文的SaveChanges方法记录结果集里实体的各种增/删/改。
    先到BreakAwayContext类里添加一个属性标识使用数据库上下文的SaveChanges方法还是使用自定义的SaveChanges方法:public bool LogChangesDuringSave { get; set; }

    来看一个方法:

            /// <summary>
            /// 记录结果集的各种:增 / 删 /改
            /// </summary>
            private static void TestSaveLogging()
            {
                using (var context = new DbContexts.DataAccess.BreakAwayContext())
                {
                    var canyon = (from d in context.Destinations
                                  where d.Name == "Grand Canyon"
                                  select d).Single();//加载主表数据
    
                    context.Entry(canyon).Collection(d => d.Lodgings).Load();//显示加载出从表相关数据
                    canyon.TravelWarnings = "Take a hat!";//修改主表字段
                    context.Lodgings.Remove(canyon.Lodgings.First());//删除相关联从表的第一条数据
                    context.Destinations.Add(new DbContexts.Model.Destination { Name = "Seattle, WA" });//添加一条主表数据
                    context.LogChangesDuringSave = true;  //设置标识,使用自定义的SaveChanges方法
                    context.SaveChanges();
                }
            }

    增加、修改、删除操作等都有。运行这个方法前需要在BreakAwayContext类里添加记录的帮助类方法:

            /// <summary>
            /// 记录帮助类方法
            /// </summary>
            private void PrintPropertyValues(DbPropertyValues values, IEnumerable<string> propertiesToPrint, int indent = 1)
            {
                foreach (var propertyName in propertiesToPrint)
                {
                    var value = values[propertyName];
                    if (value is DbPropertyValues)
                    {
                        Console.WriteLine("{0}- Complex Property: {1}", string.Empty.PadLeft(indent), propertyName);
                        var complexPropertyValues = (DbPropertyValues)value;
                        PrintPropertyValues(complexPropertyValues, complexPropertyValues.PropertyNames, indent + 1);
                    }
                    else
                    {
                        Console.WriteLine("{0}- {1}: {2}", string.Empty.PadLeft(indent), propertyName, values[propertyName]);
                    }
                }
            }
            private IEnumerable<string> GetKeyPropertyNames(object entity)
            {
                var objectContext = ((IObjectContextAdapter)this).ObjectContext;
                return objectContext.ObjectStateManager.GetObjectStateEntry(entity).EntityKey.EntityKeyValues.Select(k => k.Key);
            }

    再在BreakAwayContext类里重写下上下文的SaveChanges方法:

            /// <summary>
            /// 重写SaveChanges方法
            /// </summary>
            public override int SaveChanges()
            {
                if (LogChangesDuringSave)  //根据表示判断用重写的SaveChanges方法,还是普通的上下文SaveChanges方法
                {
                    var entries = from e in this.ChangeTracker.Entries()
                                  where e.State != EntityState.Unchanged
                                  select e;   //过滤所有修改了的实体,包括:增加 / 修改 / 删除
                    foreach (var entry in entries)
                    {
                        switch (entry.State)
                        {
                            case EntityState.Added:
                                Console.WriteLine("Adding a {0}", entry.Entity.GetType());
                                PrintPropertyValues(entry.CurrentValues, entry.CurrentValues.PropertyNames);
                                break;
                            case EntityState.Deleted:
                                Console.WriteLine("Deleting a {0}", entry.Entity.GetType());
                                PrintPropertyValues(entry.OriginalValues, GetKeyPropertyNames(entry.Entity));
                                break;
                            case EntityState.Modified:
                                Console.WriteLine("Modifying a {0}", entry.Entity.GetType());
                                var modifiedPropertyNames = from n in entry.CurrentValues.PropertyNames
                                                            where entry.Property(n).IsModified
                                                            select n;
                                PrintPropertyValues(entry.CurrentValues, GetKeyPropertyNames(entry.Entity).Concat(modifiedPropertyNames));
                                break;
                        }
                    }
                }
                return base.SaveChanges();  //返回普通的上下文SaveChanges方法
            }

    运行结果为:

    所有添加/修改/删除都记录下来了,这个可以方便我们在写程序的时候做更细微的控制,毕竟EF对实体操作的依据就是实体的各种状态。

    本文源码

    EF DbContext 系列文章导航
    1. EF如何操作内存中的数据和加载外键数据:延迟加载、贪婪加载、显示加载  本章源码
    2. EF里单个实体的增查改删以及主从表关联数据的各种增删改查  本章源码
    3. 使用EF自带的EntityState枚举和自定义枚举实现单个和多个实体的增删改查  本章源码
    4. EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态  本章源码
    5. EF里如何定制实体的验证规则和实现IObjectWithState接口进行验证以及多个实体的同时验证  本章源码
    6. 重写ValidateEntity虚方法实现可控的上下文验证和自定义验证  本章源码
    posted on 2014-02-25 19:42 NET未来之路 阅读(...) 评论(...) 编辑 收藏

    转载于:https://www.cnblogs.com/lonelyxmas/p/3567534.html

    展开全文
  • 在以前的一篇文章Visual C中轻松浏览数据库记录中我们介绍了用Visual C#如何把数据表中的字段绑定到文本框的属性如何操作数据记录指针随意浏览数据表中的记录本文就接着上一篇的内容来介绍用Visual C#如何来...
  • 它是有几个相关构 成的复合变量,是表中单行数据结构的一个镜像,可用于支持SELECT语句的返回值。记录 将一行数据看成一个单元,而不是将每一列单独处理 定义 TYPE record_type IS RECORD ( ...

    目录

    复合数据类型

    PL/SQL  记录

    %ROWTYPE属性

    游标

    隐式游标

    显示游标

    显示游标的属性

    游标和for循环

    带参数的游标

    FOR UPDATE 子句


    复合数据类型

    复数据类型包括:

    • 记录
    • 关联数组(index by表)
    • 嵌套表
    • 可变长度数组

    PL/SQL  记录

    和C++中的结构体比较像。

    它是有几个相关值构 成的复合变量,是表中单行数据结构的一个镜像,可用于支持SELECT语句的返回值。记录 将一行数据看成一个单元,而不是将每一列单独处理 

    定义

    TYPE record_type IS RECORD  
        (   
            Variable_1 datatype1[,   
            Variable_2 datatype2[,   ...]]  
        ); 

    注意这样定义的是类型,还要再定义这个类型的变量。

    例:

    DECLARE  
        TYPE NewRecordTYPE IS RECORD  
        (   
            id number,
            name varchar2(10)  
        );  
        recTest NEWRECORDTYPE;    
    BEGIN  
        SELECT empno,ename INTO recTest    
            FROM emp WHERE empno=7369;  
        DBMS_OUTPUT.PUT_LINE  
            (recTest.id||'号员工的姓名是'||recTest.name);    
    END;

    %ROWTYPE属性

    声明的变量对应于数据库表或视图中列的集合。在%ROWTYPE之前加上数据库表名。字段表示表中的列。

    这种数据类型可以一个变量把整个表的东西读出来,用".元素名"使用。

    DECLEAR 
        emp_rec    emp%rowtype;
    BEGIN
        select * into emp_rec
        from emp
        where empno=7788;
    
        INSERT INTO test VALUES 
            (emp_rec.EMPNO,emp_rec.ENAME,...,)
        commit;
    END;

    游标

    游标是一种PL/SQL控制结构,可以对SQL语句 的处理进行显式控制,便于对游标的行数据逐条进行处理。 
    分为隐式游标显式游标。

    例如删除数据时删除掉多少行数据,就通过隐式游标来获得。

    隐式游标

    从EMP中删除指定部门,返回删除的行的数量。

    DECLARE
        v_deptno    NUMBER := 20;
        v_rows_deleted    VARCHAR2(30);
    BEGIN
        DELETE FROM emp
        WHERE deptno = v_deptno;
        v_rows_deleted := SQL%ROWCOUNT;
        dbms_output.put_line(v_rows_deleteed || 'rows deleted.');
    END;

    显示游标

    需要自己定义打开显示关闭。

    理解:游标存在指针,从刚开始指向第一条,逐渐移动来遍历结果集。

    操作:

    • 定义游标
    • 打开游标
    • 提取游标
    • 关闭游标

    注意:一点特殊的是,遍历到的结果集不能再取了,即只能顺着遍历,不能倒回来看。

    声明

    CURSOR cur_name IS 
        select statement

    打开游标

    OPEN cur_name

    提取游标

    FETCH cur_name INTO [variable1,variable2,...]

    关闭游标

    关闭游标释放占用的内存空间,不写也是不出问题的。

    CLOSE cur_name

    例子:

    DECLARE
        v_ename    emp.name%TYPE;
        v_sal    emp.sal%TYPE;
        CURSOR    cur_emp    IS
            select ename,sal
            from emp
            where sal>2000;
    BEGIN
        OPEN cur_emp;
        FETCH cur_emp INTO v_ename,v_sal;
        dbms_output.putline(v_ename || ' ' || v_sal);
        FETCH cur_emp INTO v_ename,v_sal;
        dbms_output.put_line(v_ename || ' ' || v_sal;
        CLOSE cur_emp;
    END;

    显示游标的属性

    属性 类型 描述
    %ISOPEN bool 游标打开的为TRUE
    %NOTFOUND bool FETCH语句没有返回数据是TRUE
    %FOUND bool FETCH返回一行记录则为TRUE
    %ROWCOUNT 数值 返回到现在为止从游标中取出的记录数目

    例子

    DECLARE
        v_ename    emp.name%TYPE;
        v_sal    emp.sal%TYPE;
        CURSOR    cur_emp    IS
            select ename,sal
            from emp
            where sal>2000;
    BEGIN
        IF NOT cur_emp%ISOPEN THEN
            OPEN cur_emp;
        END IF;
        LOOP
            FETCH cur_emp INTO v_ename,v_sal;
            EXIT WHEN cur_emp%NOTFOUND;
            dbms_output.putline(cur_emp%ROWCOUNT);
            dbms_output.put_line(v_ename || ' ' || v_sal);
        END LOOP;
        CLOSE cur_emp;
    END;

    游标和for循环

    • 游标式的for循环可以方便的处理显示游标。
    • 隐式的打开提取和关闭游标。
    • 隐式声明记录类型变量。
    DECLARE 
        CURSOR emp_cursor IS
            SELECT empno,ename FROM emp;
    BEGIN
        FOR emp_record IN emp_cursor LOOP
            dbms_opyput.putline(emp_record.empno);
        END LOOP;
    END;

    带参数的游标

    每次传入不同值可以获得不同的结果集。更灵活

    DECLARE
        CURSOR    cur_emp (p_sal NUMBER)    IS
            select ename,sal
            from emp
            where sal>2000;
    BEGIN
        FOR rec_emp IN cur_emp(2000) LOOP
            dbms_output.put_line(v_ename || ' ' || v_sal);
        END LOOP;
    END;

    简单循环 

    DECLARE
        CURSOR    cur_emp (p_sal NUMBER)    IS
            select ename,sal
            from emp
            where sal>2000;
        rec_emp cur_emp%ROWTYPE
    BEGIN
        OPEN cur_emp(3000);
        LOOP
            FETCH cur_emp INTO rec_emp;
            EXIT when cur_emp%NOTFOUND;
            dbms_output.put_line(v_ename || ' ' || v_sal);
        END LOOP;
        CLOSE cur_emp;
    END;

    FOR UPDATE 子句

    用游标对结果集进行修改。期间需要加锁以拒绝访问。

    语法

    SELECT ...
    FROM ...
    FOR UPDATE [OF column_reference][NOWAIT];

    noway表示其他请求无需等待,直接返回错误。

    SELECT *
    FROM emp
    WHERE empno=7788
    FOR UPDATE nowait;

     

    展开全文
  • 数据库的字段属性

    2021-04-02 22:56:10
    可以自定义设计主键自增的起始值和步长 非空:NULL not null 假设设置为not null,如果不给它赋值,就会报错! NUll,如果不填写值,默认就是null! 默认: 设置默认的值 sex,默认值为男,如果不
  • 我想到的方法是添加一个名为log的新表,它存储旧,新,列名,itemID时间戳.做这个的最好方式是什么?是否有任何现有的方法/选项/示例?谢谢,解决方法:您可能正在寻找的是审计日志.您可以在MySQ...
  • 可以自定义设计主键的起始值和步长 非空 not null 假设设置为not null;则不给它赋值,就会报错; null;如果不填写值,就默认为null; 默认 设置默认的值 eg: sex,默认值是男,如果不指定该类的值,则会有...
  • 可以自定义设计主键的起始值和步长 非空not null 假设设置为not null ,如果不给它赋值,就会报错! 如果设置为null,不填写默认值就是null! 默认 设置默认值 如果不指定该列的值,则会有默认的值 拓展:每一...
  • 可以自定义设置主键自增的起始值和步长 非空 假设设置为not null,如果不给他赋值就会报错 假设设置为null,如果不给他赋值就默认为null 表中最好有的几个字段 id 主键 version 乐观锁 is_d
  • 用Visual C#来修改删除数据库记录

    千次阅读 2005-01-10 02:08:00
    在以前的一篇文章《Visual C#中轻松浏览数据库记录》中,我们介绍了用Visual C#如何把数据表中的字段绑定到文本框的属性如何操作数据记录指针,随意浏览数据表中的记录。本文就接着上一篇的内容,来介绍用...
  • 问题原因: Hiberate对象状态 1.瞬态: 一个实体通过new操作符创建后,没有Hibernate的Session建立...此时针对该实体任何属性的更改都会直接影响到数据库表中一条记录对应字段的更新,即与数据库表同步。 3.脱管:
  • 在以前的一篇文章《Visual C#中轻松浏览数据库记录》中,我们介绍了用Visual C#如何把数据表中的字段绑定到文本框的属性如何操作数据记录指针,随意浏览数据表中的记录。本文就接着上一篇的内容,来介绍用...
  • 在以前的一篇文章《Visual C#中轻松浏览数据库记录》中,我们介绍了用Visual C#如何把数据表中的字段绑定到文本框的属性如何操作数据记录指针,随意浏览数据表中的记录。本文就接着上一篇的内容,来介绍用...
  • 8.数据库的字段属性

    2021-04-07 20:49:48
    可以自定义设计主键自增的起始值和步长(高级) 非空 NUll not null 假设设置为not null,如果不给他赋值,就会报错 Null,如果不填写,默认值就是null 默认 设置默认值! sex,默认值为男,如果不指定该列的值,
  • mysql数据库表格属性

    2020-06-29 23:53:39
    可以自定义主键自增的起始值和步长 非空null not null 假设设置为not null 如果不给它赋值,就会报错 null ,如果不填写值,默认就是mull 默认 设置默认的值 sex,默认值为男,不指定值会默认值 ...
  • JAVA打怪升级-反射比较对象属性和属性值        最近开发遇到一个比较相同对象的同一字段的属性值,然后将对象的两次变化数据保存到数据库中的需求,这个对象实体字段比较多,...
  • Unsigned 无符号的整数 表示了该列不能声明为负数 zerofill ...不足的位数用0填充 例如 int(8) 12 填充为 00000012 ...可以自定义设置主键自增的起始值和步长 null 和not null 设置为not null后不赋值就是...
  • 2.3、数据库的字段属性(重点)Unsigned:无符号的整数声明了该列不能为负数zerofill:0填充的不足的位数,使用0来填充,int(3) ,5 ---005自增:通常理解为自增,自动在上一条记录的基础上+1(默认)通常用来设计唯一的...
  • 数据库的字段属性(重点) Unsigned: 无符号的整数(不能为负数) zerofill: 0填充的,不足的位数将会用0填充 自增: 在上一条记录的基础上+1(默认) 通常用于设置唯一主键,必须是整数类型 可以自定义主键...
  • 可以自定义设计主键自增的起始值和步长 非空 NULL,not null 假设设置为not null,如果不给它赋值,就会报错! NULL,如果不填写值,默认就是null! 默认: 设置默认的值 sex,默认值为男,如果不指定该列的值,...
  • 1.原子性:每一列的属性值不可再分 2.原始性:对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;要求每张表只表达一个意思 3.所有字段都主键直接相关,如果要其他表建立关联,可以增加外键。 ...
  • 一. 数据库的字段属性(重点) 1.1 Unsigned(无符号数) 无符号数的整数 ...可以自定义设计主键自增的起始值和步长 1.4 非空 NULL,not null 假设选择了非空,如果不给她赋值,就会报错 NULL,不填写值,默认

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,350
精华内容 540
关键字:

数据库记录值和属性值