精华内容
下载资源
问答
  • 绿色工具里,可以对多个字段打上主键的标识“锁”,但这并不表示拥有了多个主键,而是说这几个字段共同构成了主键。当然,他们之间也有次序的。查看次序可以使用show index from table。会看到Key_Name有多...

    在绿色工具里,可以对多个字段打上主键的标识“锁”,但这并不表示表拥有了多个主键,而是说这几个字段共同构成了主键。当然,他们之间也是有次序的。查看次序可以使用show index from table。会看到Key_Name中有多个Primary,而Seq_in_index便是指各字段在主键中的优先顺序,当然了,对多个字段构成的索引也是一样的道理。

    展开全文
  • 1.概述:  在我们的数据库设计... 自增量字段每次都会按顺序递增,可以保证在一个表里的主键不重复。除非超出了自增字段类型的最大值并从头递增,但这几乎不可能。使用自增量字段来做主键是非常简单的,一般

    1.概述:

      在我们的数据库设计中,数据库的主键是必不可少的,主键的设计对整个数据库的设计影响很大.我就对自动增量字段与Guid字段的性能作一下对比,欢迎大家讨论.

    2.简介:

      1.自增量字段

          自增量字段每次都会按顺序递增,可以保证在一个表里的主键不重复。除非超出了自增字段类型的最大值并从头递增,但这几乎不可能。使用自增量字段来做主键是非常简单的,一般只需在建表时声明自增属性即可。

          自增量的值都是需要在系统中维护一个全局的数据值,每次插入数据时即对此次值进行增量取值。当在当量产生唯一标识的并发环境中,每次的增量取值都必须最此全局值加锁解锁以保证增量的唯一性。这可能是一个并发的瓶颈,会牵扯一些性能问题。

      在数据库迁移或者导入数据的时候自增量字段有可能会出现重复,这无疑是一场恶梦(本人已经深受其害).

          如果要搞分布式数据库的话,这自增量字段就有问题了。因为,在分布式数据库中,不同数据库的同名的表可能需要进行同步复制。一个数据库表的自增量值,就很可能与另一数据库相同表的自增量值重复了。

      2.uniqueidentifier(Guid)字段

       在MS Sql 数据库中可以在建立表结构是指定字段类型为uniqueidentifier,并且其默认值可以使用NewID()来生成唯一的Guid(全局唯一标识 符).使用NewID生成的比较随机,如果是SQL 2005可以使用NewSequentialid()来顺序生成,在此为了兼顾使用SQL 2000使用了NewID().

      Guid:指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,其算法是通过以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字生成。其格式为:04755396-9A29-4B8C-A38D-00042C1B9028.

       Guid的优点就是生成的id比较唯一,不管是导出数据还是做分步开发都不会出现问题.然而它生成的id比较长,占用的数据库空间也比较多,随着外存价格的下降,这个也无需考虑.另外Guid不便于记忆,在这方面不如自动增量字段,在作调试程序的时候不太方便。

    3.测试:

      1.测试环境

      操作系统:windows server 2003 R2 Enterprise Edition Service Pack 2

      数据库:MS SQL 2005

      CPU:Intel(R) Pentium(R) 4 CPU 3.40GHz

      内存:DDRⅡ 667  1G

      硬盘:WD 80G

      2.数据库脚本  

    --自增量字段表
    CREATE TABLE [dbo].[Table_Id](
        
    [Id] [int] IDENTITY(1,1NOT NULL,
        
    [Value] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
     
    CONSTRAINT [PK_Table_Id] PRIMARY KEY CLUSTERED 
    (
        
    [Id] ASC
    )
    WITH (IGNORE_DUP_KEY = OFFON [PRIMARY]
    ON [PRIMARY]

    GO
    --Guid字段表
    CREATE TABLE [dbo].[Table_Guid](
        
    [Guid] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Table_Guid_Guid]  DEFAULT (newid()),
        
    [Value] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
     
    CONSTRAINT [PK_Table_Guid] PRIMARY KEY CLUSTERED 
    (
        
    [Guid] ASC
    )
    WITH (IGNORE_DUP_KEY = OFFON [PRIMARY]
    ON [PRIMARY]

    GO

     

      测试代码  

      1using System;
      2using System.Collections.Generic;
      3using System.Text;
      4using System.Data.SqlClient;
      5using System.Diagnostics;
      6using System.Data;
      7
      8namespace GuidTest
      9{
     10    class Program
     11    
     12        string Connnection = "server=.;database=GuidTest;Integrated Security=true;";
     13        static void Main(string[] args)
     14        {
     15            Program app = new Program();
     16            int Count = 10000;
     17            Console.WriteLine("数据记录数为{0}",Count);
     18            //自动id增长测试;
     19            Stopwatch WatchId = new Stopwatch();
     20            Console.WriteLine("自动增长id测试");
     21            Console.WriteLine("开始测试");
     22            WatchId.Start();
     23            Console.WriteLine("测试中");
     24
     25            app.Id_InsertTest(Count);
     26            //app.Id_ReadToTable(Count);
     27            //app.Id_Count();
     28
     29            //查询第300000条记录;
     30            //app.Id_SelectById();
     31
     32            WatchId.Stop();
     33            Console.WriteLine("时间为{0}毫秒",WatchId.ElapsedMilliseconds);
     34            Console.WriteLine("测试结束");
     35
     36            Console.WriteLine("-----------------------------------------");
     37            //Guid测试;
     38            Console.WriteLine("Guid测试");
     39            Stopwatch WatchGuid = new Stopwatch();
     40            Console.WriteLine("开始测试");
     41            WatchGuid.Start();
     42            Console.WriteLine("测试中");
     43
     44            app.Guid_InsertTest(Count);
     45            //app.Guid_ReadToTable(Count);
     46            //app.Guid_Count();
     47
     48            //查询第300000条记录;
     49            //app.Guid_SelectById();
     50
     51            WatchGuid.Stop();
     52            Console.WriteLine("时间为{0}毫秒", WatchGuid.ElapsedMilliseconds);
     53            Console.WriteLine("测试结束");
     54            Console.Read();
     55        }

     56
     57        /// 
     58        /// 自动增长id测试
     59        /// 

     60        private void Id_InsertTest(int count)
     61        {
     62            string InsertSql="insert into Table_Id ([Value]) values ({0})";
     63            using (SqlConnection conn = new SqlConnection(Connnection))
     64            {
     65                conn.Open();
     66                SqlCommand com = new SqlCommand();
     67                for (int i = 0; i < count; i++)
     68                {
     69                    com.Connection = conn;
     70                    com.CommandText = string.Format(InsertSql, i);
     71                    com.ExecuteNonQuery();
     72                }

     73            }

     74        }

     75
     76        /// 
     77        /// 将数据读到Table
     78        /// 

     79        private void Id_ReadToTable(int count)
     80        {
     81            string ReadSql = "select top " + count.ToString() + " * from Table_Id";
     82            using (SqlConnection conn = new SqlConnection(Connnection))
     83            {
     84                SqlCommand com = new SqlCommand(ReadSql, conn);
     85                SqlDataAdapter adapter = new SqlDataAdapter(com);
     86                DataSet ds = new DataSet();
     87                adapter.Fill(ds);
     88                Console.WriteLine("数据记录数为:{0}", ds.Tables[0].Rows.Count);
     89            }

     90        }

     91
     92        /// 
     93        /// 数据记录行数测试
     94        /// 

     95        private void Id_Count()
     96        {
     97            string ReadSql = "select Count(*) from Table_Id";
     98            using (SqlConnection conn = new SqlConnection(Connnection))
     99            {
    100                SqlCommand com = new SqlCommand(ReadSql, conn);
    101                conn.Open();
    102                object CountResult = com.ExecuteScalar();
    103                conn.Close();
    104                Console.WriteLine("数据记录数为:{0}",CountResult);
    105            }

    106        }

    107
    108        /// 
    109        /// 根据id查询;
    110        /// 

    111        private void Id_SelectById()
    112        {
    113            string ReadSql = "select * from Table_Id where Id="+300000;
    114            using (SqlConnection conn = new SqlConnection(Connnection))
    115            {
    116                SqlCommand com = new SqlCommand(ReadSql, conn);
    117                conn.Open();
    118                object IdResult = com.ExecuteScalar();
    119                Console.WriteLine("Id为{0}", IdResult);
    120                conn.Close();
    121            }

    122        }

    123        
    124        /// 
    125        /// Guid测试;
    126        /// 

    127        private void Guid_InsertTest(int count)
    128        {
    129            string InsertSql = "insert into Table_Guid ([Value]) values ({0})";
    130            using (SqlConnection conn = new SqlConnection(Connnection))
    131            {
    132                conn.Open();
    133                SqlCommand com = new SqlCommand();
    134                for (int i = 0; i < count; i++)
    135                {
    136                    com.Connection = conn;
    137                    com.CommandText = string.Format(InsertSql, i);
    138                    com.ExecuteNonQuery();
    139                }

    140            }

    141        }

    142
    143        /// 
    144        /// Guid格式将数据库读到Table
    145        /// 

    146        private void Guid_ReadToTable(int count)
    147        {
    148            string ReadSql = "select top "+count.ToString()+" * from Table_GuID";
    149            using (SqlConnection conn = new SqlConnection(Connnection))
    150            {
    151                SqlCommand com = new SqlCommand(ReadSql, conn);
    152                SqlDataAdapter adapter = new SqlDataAdapter(com);
    153                DataSet ds = new DataSet();
    154                adapter.Fill(ds);
    155                Console.WriteLine("数据记录为:{0}", ds.Tables[0].Rows.Count);
    156            }

    157        }

    158
    159        /// 
    160        /// 数据记录行数测试
    161        /// 

    162        private void Guid_Count()
    163        {
    164            string ReadSql = "select Count(*) from Table_Guid";
    165            using (SqlConnection conn = new SqlConnection(Connnection))
    166            {
    167                SqlCommand com = new SqlCommand(ReadSql, conn);
    168                conn.Open();
    169                object CountResult = com.ExecuteScalar();
    170                conn.Close();
    171                Console.WriteLine("数据记录为:{0}", CountResult);
    172            }

    173        }

    174
    175        /// 
    176        /// 根据Guid查询;
    177        /// 

    178        private void Guid_SelectById()
    179        {
    180            string ReadSql = "select * from Table_Guid where Guid='C1763624-036D-4DB9-A1E4-7E16318C30DE'";
    181            using (SqlConnection conn = new SqlConnection(Connnection))
    182            {
    183                SqlCommand com = new SqlCommand(ReadSql, conn);
    184                conn.Open();
    185                object IdResult = com.ExecuteScalar();
    186                Console.WriteLine("Guid为{0}", IdResult);
    187                conn.Close();
    188            }

    189        }

    190    }

    191
    192}

    193

     

      3.数据库的插入测试

      测试1

      数据库量为:100条

      运行结果

     

      测试2

      数据库量为:10000条

    运行结果

     
    测试3

      数据库量为:100000条

    运行结果 

     

      测试4

      数据库量为:500000条

      运行结果

       4.将数据读到DataSet中

      测试1

      读取数据量:100

      运行结果

      测试2

      读取数据量:10000

      运行结果

     

      测试3

      读取数据量:100000

      运行结果

       测试4

      读取数据量:500000

      运行结果

     

      4.记录总数测试

      测试结果

      5.指定条件查询测试

    查询数据库中第300000条记录,数量记录量为610300.

    4.总结:

      使用Guid作主键速度并不是很慢,它反而要比使用自动增长型的增量速度还要快.

    5.参考:

      http://www.cnblogs.com

      http://www.cnblogs.com/leadzen/archive/2008/05/10/1191010.html

    5.2.2  选择主键

        主键是能够惟一地定义一行数据的一列或多列。主键中的列值不能设置为null值。主键为数据库引擎提供了一种获取数据库表中某个特定行的方法。主键还用于保证引用的完整性。在处理非连接数据时,如果多个用户同时插入数据,则必须确保不会出现重复的主键。

    1. 对比智能键、常规键和代理键

    智能键是一种基于商业数据表示的键。例如,SKU(Stock Keeping Unit,常用保存单元)就是智能键的一个例子,它定义为一个包含10个字符的字段(在数据库中定义为CHAR(10))。该SKU可能包含以下信息:前四个字符保存供应商代号,随后的三个字符保存产品类型代号,最后三个字符保存一个序列号。

    常规键(natural primary key)由商业数据中现有的单个或多个列构成,用于惟一地标识记录。例如,某个现有的商业过程可能要使用社会保险号来标识医院的患者。

    尽管智能键和常规键互不相同,但它们都由使用商业相关数据的列构成,并且用户一般都可以查看它们。本书以后将这些键统一称为智能键。

    代理主键的键值是由系统生成的,这些值与行中的商业数据没有关系,因此又称为非智能键(dumb key)。本书以后将这些键统一称为代理键(surrogate key)。自动增值的列就是这种键的一个例子,在添加新的行时,该列的值将相应地设置为123…,依此类推。在Microsoft SQL Server中,自动增值的列称为Identity列。本书以后将这种键统一称为Identity(identity key)GUID(globally unique identifier,全局惟一标识符)是另一个由系统生成键值的例子,它通过使用取值算法来生成惟一的键值。本书以后将这种键统一称为GUID键。

    专家推荐使用哪一种主键类型呢?不同的专家有着各自的见解。大家在做出选择之前,应深入地理解各种方法的主要优缺点。

    5.3显示了智能键和代理键的一种实现示例。该示例包含三个表:第一个表用于保存作者数据,第二个表用于保存书籍数据,第三个表是一个多对多的联接表(join table),因为一个作者能够编写多本书籍,一本书籍也能够由多个作者共同编写。

    注意,代理主键的实现在TblAuthorTblBook表中额外包含了一个Id列,因为代理主键的键值是由系统生成的,与行数据无关。用户应不能看见代理主键。下面,我们将分析智能键与代理主键之间在实现上的差异。

    数据大小 数据大小本身并不十分重要,重要的是在数据库和客户之间传输数据时所占用的带宽。代理主键的实现在每个主表中都额外增加了一列。这将显著地增大数据量的大小。如果代理主键是一个GUID列,则增加的列将使每行增加16个字节。如果增加的是一个自动增值的列,则因该列引起的数据增量取决于所选用的数据类型(int型增加4个字节,long型增加8个字节)。由于联接表通常包含数量庞大的行记录,因此在分析数据库大小的总体差异时,一定要考虑到智能键与代理主键在数据增量大小方面的差异。此外,主键通过创建一个惟一索引来确保自身的惟一性,因此还要考虑到这方面的数据增量。表5.1列出了每种主键类型在数据增量方面的比较结果。

                              智能键                              代理键

    图5.3 智能键和代理键的实现示例

    表5.1 主键大小示例

    描述

    智能键

    Identity键(int型)

    GUID键

    1000条作者记录

    9个字节/SSN = 9,000个字节

    4个字节/int = 4,000个字节

    16个字节/GUID = 16,000个字节

    3000条书籍记录

    10个字节/ISBN = 30,000个字节

    4个字节/int = 12,000个字节

    16个字节/GUID = 48,000个字节

    10,000条作者/书籍记录

    19个字节/= 190,000个字节

    8个字节/ = 80,000个字节

    32个字节/ = 320,000个字节

    小计

    229,000个字节

    96,000个字节

    384,000个字节

    索引

    229,000个字节

    96,000个字节 + 9000SSN + 30,000ISBN = 135,000个字节

    384,000个字节 + 9000SSN + 30,000ISBN = 423,000个字节

    总数

    458,000个字节

    231,000个字节

    807,000个字节

     

    显然,Identity键是这一比较回合的赢家,但要记住的是,int型的最大值是231-1=2 147 483 647。对于大多数应用程序而言,该值已经足够了,但是有些应用程序需要使用long数据类型来保存更多的记录。注意,计算不同类型索引大小的方法是互不相同的。代理键的实现仍需要在SSN列和ISBN列上提供一个惟一索引,以确保这些列的惟一性。

    键的可见性 代理键对用户是不可见的,但智能键是可见的,并且用户知道如何使用智能键。客户应用程序可以隐藏代理键,但数据库工具却不能隐藏它们。这就要求使用数据库工具的人员必须理解如何使用代理键。因此,智能键是这一比较回合的赢家。

    键的易修改性 主键是难以进行修改的,因为如果对主键进行修改,则修改结果必然对子表造成影响。这时就应该使用代理键取代智能键。为什么呢?因为代理键并不显示给用户,所以不必修改它们;而智能键包含用户可以看到的商业数据,因此必须允许该数据能够进行修改。

    int型代理键也需要进行修改,以确保惟一性(正如前文所述),但GUID型代理键从不需要进行修改。这正是我为什么喜欢使用GUID型代理键的主要原因。

    联接个数 在某些情况中,可以使用智能键来减少联接的个数。例如,如果想运行一个显示每个作者所著书籍的报表,并且该报表只包含作者的SSN字段和书籍的ISBN字段,则在实现智能主键时,只需查询TblAuthorBook联接表即可。在实现代理主键时,必须联合查询TblAuthor表、TblAuthorBook表和TblBook表才能获得该信息。因此,智能键是这一比较回合的赢家,但实践中很少只查询这两列信息而不查询其他的信息,诸如作者的姓名和书名。

    SQL复杂性 智能键的实现通常使用多个列来确保惟一性。SQL查询会因为使用这样的复合智能键而变得错综复杂。正如前文所述,尽管可以联合更多的代理键,但代理键更易于使用,因为它们不使用复合键(联接表除外)。对比前面两种代理键类型,Identity键在实现上比GUID键更易于编写查询,但是一旦掌握了GUID数据类型(稍后将会予以讨论)的使用特点,就会发现,GUID键相较于Identity键,并不是特别难用的。

    在非连接时确保惟一性 在 非连接环境中,几乎不能保证智能键在用户输入数据时的惟一性。问题是在向数据库服务器添加新行时,有人可能输入匹配信息,从而导致冲突。有人可能会辩解 说,使用代理键就可以解决该问题,但不要忘记,大家仍可以在诸如社会保险号或车辆标识号等字段上创建惟一索引,以在添加重复信息时能抛出一个异常。

    在使用int型代理键时,管理主键列编号的窍门是将DataSet非连接对象中的AutoIncrement属性设置为trueAutoIncrementStep(增量)设置为-1(1)AutoIncrementSeed(起始值)设置为-1,这样,在添加新行时,编号将从-1开始,每新增一行,编号就减1。负值认为是非连接占位符,因此不会与服务器的Identity列设置产生冲突,因为服务器只会分配正值编号。下面的SQL命令首先插入一行数据,然后立即查询该插入行。该命令所返回的信息用于将占位符(负值键)更新为数据库所创建的值。

    SQL INSERT命令

    INSERT INTO [TBLAUTHOR] ([SSN], [LastName], [FirstName])

        VALUES (@SSN, @LastName, @FirstName)

    SELECT Id, SSN, LastName, FirstName FROM TblAuthor

        WHERE (Id = SCOPE_IDENTITY())

     

    SCOPE_IDENTITY函数返回刚才所插入的作者ID值。注意,不要使用@@IDENTITY函数,因为在激活一个插入触发器,以在包含Identity列的表中插入一行或多行数据时,该函数将返回一个错误值。

    因为必须获取服务器中的 数据来更新非连接数据中的占位符,所以必须考虑更新主键值对性能的影响。如果使用服务器中创建的值更新非连接数据键,会发生什么情况呢?这时,所有的子数 据都必须进行更新,以反映键值的变化;为实现这一目的,可以根据它们之间的相互关系启用级联更新功能。这又会引出另一个性能问题,尤其对于较大的DataSet对象。

    在使用GUID代理主键时,一旦设置了主键就不必再修改它。主要的问题是如何设置键值。下面的代码片段演示了如何初始化GUID

    Visual Basic

    Private Sub Form1_Load(ByVal sender As System.Object, _

           ByVal e As System.EventArgs) Handles MyBase.Load

        For Each dt As DataTable In salesSurrogateGuidKeyDs.Tables

           If (not dt.Columns("Id") Is Nothing) Then

               AddHandler dt.TableNewRow, addressof InitializeGuid

           End If

        Next

    End Sub

    Private Sub InitializeGuid(ByVal sender As Object, _

           ByVal e As DataTableNewRowEventArgs)

        If (TypeOf e.Row("Id") Is DBNull) Then

           e.Row("Id") = Guid.NewGuid()

        End If

    End Sub

    C#

    public Form1() //constructor

    {

        InitializeComponent();

        foreach (DataTable dt in sales_SurrogateGuidKeyDs.Tables)

        {

            if(dt.Columns["Id"] != null)

                dt.TableNewRow += new DataTableNewRowEventHandler(InitializeGuid);

        }

    }

    private void InitializeGuid(object sender, DataTableNewRowEventArgs e)

    {

        if(e.Row["Id"] is DBNull)

            e.Row["Id"] = Guid.NewGuid();

    }

     

    因为TblAuthor表和TblBook表具有同名的主键(Id),所以前面的示例代码包含一个InitializeGuid方法,用于创建新的GUID,在触发这些表的TableNewRow事件时,将调用该方法。通常,像该示例代码那样,使所有的代理键具有相同的名称是一种不错的做法。不必使用该实现创建级联关系。所以,GUID型代理键是这一比较回合的赢家。

    在数据库间移动数据 在实现Identity键时,需要额外做一些工作才能在数据库之间移动数据。假设表的键值范围从1n,这些值也可以作为数据库中所有外键的值。如何取出该数据,并将其合并到另一个使用相同数据编号的数据库中呢?要想解决这一问题,则需要对所有的Identity列进行重新编号。

    如果使用GUID键实现,则移动数据只是将数据从一个数据库复制到另一个数据库,因此,GUID键是这一比较回合的赢家。

    最终的赢家是… 我刚刚开发完成了一项实现GUID键的大型项目,并且还开发了多个使用智能键和Identity键实现的项目。表5.2总结了各种键类型在一些影响性能、数据大小和易用性等因素中所占的百分比。我根据自己使用这些键类型的经验,将权重值的范围设定为0%100%,其中100%表示权重值最大。此外,键类型的系数分为以下三级:第一级系数为1,第二级系数为0.5,第三级系数为0,通过将键类型系数乘以每个因素的权重值,就可以得到每种键类型的权重值。

    表5.2 基于因素及其权重的最终百分比

    权重值

    因素及其权重

    智能键

    Identity

    GUID

    数据大小 = 25%

    12.5%

    25%

    0%

    键的可见性 = 5%

    5%  

    2.5%

    0%

    键的易修改性 = 20%

    0%

    10%

    20%

    联接个数 = 5%

    5%

    2.5%

    2.5%

    SQL复杂性 = 5%

    0%

    5%

    2.5%

    确保惟一性 = 25%

    0%

    12.5%

    25%

    数据移动 = 15%

    7.5%

    0%

    15%

    总计 = 100%

    30%

    57.5%

    65%

     

    根据表5.2中的权重值,GUID键的绝大部分因素权重值都是最大的。如果大家对某些因素的权重存有异议,可以尝试着修改权重以验证是否能得到不同的结果。注意,这些主键的实现都不能面分之百地满足所有因素。一般认为,GUID键实现是最适合非连接数据应用程序的。智能键实现是否有属于自己的用武之地呢?有的,它最适合用于数据仓库应用程序,因为数据仓库应用程序在设计上一般都会提供高性能只读访问,并且包含最少的联接数。因为数据是只读的,所以“修改键”因素所占的权重较小。表5.3通过对表5.2中的权重进行局部调整,提供了各种键类型基于另一种权重的百分比。

    表5.3 基于因素及其权重的数据仓库百分比

    权重值

    因素及其权重

    智能键

    Identity

    GUID

    数据大小=25%

    12.5%

    25%

    0%

    键的可见性=10%

    10%

    0%

    0%

    键的易修改性=5%

    0%

    2.5%

    5%

    联接个数=25%

    25%

    0%

    0%

    SQL复杂性=10%

    10%

    5%

    5%

    确保惟一性=5%

    0%

    0%

    5%

    数据移动=20%

    10%

    0%

    20%

    总计=100%

    67.5%

    32.5%

    35%

     

        前面的表只是作为一种参考,大家在做项目的时候,一定要考虑到其他可能影响项目的任何因素。

    5.3 GUID的用法

        许多开发人员在试图使用GUID键时,对GUID感到非常恐惧。GUID可能非常大,但它们并不难以使用。下面将介绍一些使用技巧。

    5.3.1 复制/粘贴GUID

    在调试时,可以选中包含一个GUID键的代码,这时IntelliSense会显示该GUID(如图5.4所示);接着,选中该GUID键的键值,并将其复制到剪贴板;然后将该值粘贴到一个查询窗口中,并将大括号替换为单引号,如下面的SQL语句所示。

    图5.4 使用IntelliSense复制一个GUID键,并将其粘贴到查询工具中

    使用GUID键的SQL查询命令

    SELECT Id, SSN, LastName, FirstName

    FROM TblAuthor

    WHERE (Id = 'cbc8c64c-6ba6-4bec-baef-4c0e50e8b251')

    5.3.2 在非联接表中使用同名的主键列

        强烈建议大家在所有非联接表中使用同名的主键列(诸如Id)。这样做有利于编写处理GUID键的存储过程。此外,使主键成为每个表中的第一列还可以帮助用户理解该字段的目的。

    5.3.3 查找数据库中的GUID

    由于数据库的设计原因,大家在查找某个外键列中的一个GUID时,却不知道该GUID的数据在哪儿。例如,假设有一个如图5.5所示的独占性OR关系。这种类型的关系经常出现在面向对象的环境中——一个Book类可能包含多个子类,诸如Ebook类、PaperBack类和HardCover类。这些类的字段互不相同,因此要么创建一个包含大量列值为null的表,要么如图5.5所示,为每个子类单独创建一个表,必须在这两种方法中选择其一。

    图5.5 独占性OR关系的一个示例

    如果想确定某个特定的GUID包含在哪个表中,则可以使用下面的存储过程来定位将该GUID作为主键值的表。

    SQL uspGetDataForId

    CREATE PROCEDURE dbo.uspGetDataForId

    (

            @id uniqueidentifier

    )

    AS

    SET NOCOUNT ON

    --NOTE: This proc assumes that all user tables have 'Tbl' prefix

    --Usage: in Query Analyser, type the following without the '--'

    --exec uspGetDataForId '78257ec8-c8f9-4d35-a636-d58d8a67c3d4'

    DECLARE @tbl varchar(2000)

    DECLARE @sql varchar(2000)

    IF OBJECT_ID('tempdb..#idTable') IS NOT NULL DROP TABLE #idTable

    CREATE TABLE #idTable (

            Id uniqueidentifier,

            Count INT,

            TableName varchar(2000)

    )

    DECLARE tables_cursor CURSOR

        FOR SELECT TABLE_NAME FROM information_schema.Tables

            WHERE substring (TABLE_NAME,1,3)='Tbl'

    OPEN tables_cursor

    FETCH NEXT FROM tables_cursor INTO @tbl

    WHILE @@FETCH_STATUS = 0

    BEGIN

        IF EXISTS (SELECT * FROM information_schema.columns

                    WHERE table_name=@tbl AND Column_Name='Id')

        BEGIN

            SET @sql = 'INSERT INTO #idTable SELECT id as ''Id'', '

                + 'count(*) as ''Count'',''' + @tbl +''' as ''TableName'' FROM '

                + @tbl + ' WHERE ID=''' + CONVERT(varchar(2000),@id)

                + ''' group by Id'

            EXEC(@sql)

        END

        FETCH NEXT FROM tables_cursor INTO @tbl

    END

    CLOSE tables_cursor

    DEALLOCATE tables_cursor

    SELECT Id, TableName FROM #idTable WHERE Count > 0

     

        注意,该存储过程要求所有主键列的名称都为Id,用户表的前缀都为Tbl。该存储过程没有尝试在其他任何列中查找一个GUID,但如果需要查找所有使用某个GUID的位置,则要读取所有的列。

    展开全文
  • 自增量字段  自增量字段每次都会按顺序递增,可以保证在一个表里的主键不重复。除非超出了自增字段类型的最大值并从头递增,但这几乎不可能。使用自增量字段来做主键是非常简单的,一般需在建表时声明自增...

    1.概述:

      在我们的数据库设计中,数据库的主键是必不可少的,主键的设计对整个数据库的设计影响很大.我就对自动增量字段与Guid字段的性能作一下对比,欢迎大家讨论.

    2.简介:

      1.自增量字段

          自增量字段每次都会按顺序递增,可以保证在一个表里的主键不重复。除非超出了自增字段类型的最大值并从头递增,但这几乎不可能。使用自增量字段来做主键是非常简单的,一般只需在建表时声明自增属性即可。

          自增量的值都是需要在系统中维护一个全局的数据值,每次插入数据时即对此次值进行增量取值。当在当量产生唯一标识的并发环境中,每次的增量取值都必须最此全局值加锁解锁以保证增量的唯一性。这可能是一个并发的瓶颈,会牵扯一些性能问题。

      在数据库迁移或者导入数据的时候自增量字段有可能会出现重复,这无疑是一场恶梦(本人已经深受其害).

          如果要搞分布式数据库的话,这自增量字段就有问题了。因为,在分布式数据库中,不同数据库的同名的表可能需要进行同步复制。一个数据库表的自增量值,就很可能与另一数据库相同表的自增量值重复了。

      2.uniqueidentifier(Guid)字段

       在MS Sql 数据库中可以在建立表结构是指定字段类型为uniqueidentifier,并且其默认值可以使用NewID()来生成唯一的Guid(全局唯一标识符).使用NewID生成的比较随机,如果是SQL 2005可以使用NewSequentialid()来顺序生成,在此为了兼顾使用SQL 2000使用了NewID().

      Guid:指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,其算法是通过以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字生成。其格式为:04755396-9A29-4B8C-A38D-00042C1B9028.

       Guid的优点就是生成的id比较唯一,不管是导出数据还是做分步开发都不会出现问题.然而它生成的id比较长,占用的数据库空间也比较多,随着外存价格的下降,这个也无需考虑.另外Guid不便于记忆,在这方面不如自动增量字段,在作调试程序的时候不太方便。

    3.测试:

      1.测试环境

      操作系统:windows server 2003 R2 Enterprise Edition Service Pack 2

      数据库:MS SQL 2005

      CPU:Intel(R) Pentium(R) 4 CPU 3.40GHz

      内存:DDRⅡ 667  1G

      硬盘:WD 80G

      2.数据库脚本  

    --自增量字段表
    CREATE TABLE [dbo].[Table_Id](
        
    [Id] [int] IDENTITY(1,1NOT NULL,
        
    [Value] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
     
    CONSTRAINT [PK_Table_Id] PRIMARY KEY CLUSTERED 
    (
        
    [Id] ASC
    )
    WITH (IGNORE_DUP_KEY = OFFON [PRIMARY]
    ON [PRIMARY]

    GO
    --Guid字段表
    CREATE TABLE [dbo].[Table_Guid](
        
    [Guid] [
    展开全文
  • 自增量字段 自增量字段每次都会按顺序递增,可以保证在一个表里的主键不重复。除非超出了自增字段类型的最大值并从头递增,但这几乎不可能。使用自增量字段来做主键是非常简单的,一般需在建表时声明自增属性即可...

     

    2.简介:

      1.自增量字段

          自增量字段每次都会按顺序递增,可以保证在一个表里的主键不重复。除非超出了自增字段类型的最大值并从头递增,但这几乎不可能。使用自增量字段来做主键是非常简单的,一般只需在建表时声明自增属性即可。

          自增量的值都是需要在系统中维护一个全局的数据值,每次插入数据时即对此次值进行增量取值。当在当量产生唯一标识的并发环境中,每次的增量取值都必须最此全局值加锁解锁以保证增量的唯一性。这可能是一个并发的瓶颈,会牵扯一些性能问题。

      在数据库迁移或者导入数据的时候自增量字段有可能会出现重复,这无疑是一场恶梦(本人已经深受其害).

          如果要搞分布式数据库的话,这自增量字段就有问题了。因为,在分布式数据库中,不同数据库的同名的表可能需要进行同步复制。一个数据库表的自增量值,就很可能与另一数据库相同表的自增量值重复了。

      2.uniqueidentifier(Guid)字段

       在MS Sql 数据库中可以在建立表结构是指定字段类型为uniqueidentifier,并且其默认值可以使用NewID()来生成唯一的Guid(全局唯一标识符).使用NewID生成的比较随机,如果是SQL 2005可以使用NewSequentialid()来顺序生成,在此为了兼顾使用SQL 2000使用了NewID().

      Guid:指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,其算法是通过以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字生成。其格式为:04755396-9A29-4B8C-A38D-00042C1B9028.

       Guid的优点就是生成的id比较唯一,不管是导出数据还是做分步开发都不会出现问题.然而它生成的id比较长,占用的数据库空间也比较多,随着外存价格的下降,这个也无需考虑.另外Guid不便于记忆,在这方面不如自动增量字段,在作调试程序的时候不太方便。

     

    转(http://www.cnblogs.com/houleixx/archive/2008/12/13/Id_And_Guid.html

    展开全文
  • 所谓的主键,其实并非大家想象的那么神秘,主键其实也是一个字段而已,不过,该字段的任何数据,都是唯一的,没有任何两个数据相同,这就好比我们的身份证号码一样,没有任何两个人的身份证号码相同。...
  • 自增量字段每次都会按顺序递增,可以保证在一个表里的主键不重复。使用也比较简单,需在建表时声明为自增属性即可。 自增量的值需要在系统维护一个全局的数据值,每次插入数据时即对此值进行增量取值。当在...
  • 表里指定字段自增,这问题SQLSERVER里面来说很简单 ,Identity(1,1)该字段就会从1开始,按照+1的方式自增. 但是Oracle里面呢,就需要用到序列和触发器完成才可以...表中主键F_ID ,接下来就指定该列F_ID自增长
  • 今天来介绍两种Mysql主键约束。 主键定义 键是表的标识列,关系数据库依赖于主键,它...创建的同时设置主键可以放在单字段后,也可以放在的末尾 alter table 表名 modify 字段字段类型 primar...
  • Sql server主键与外键

    千次阅读 热门讨论 2012-08-04 09:37:07
    在一个表中只能设置一个主键约束,但可以将包含多个字段的字段组合设置为主键主键约束分为字段级约束和表级约束。字段级约束为某一个字段设置约束。在设置字段级约束时,需将创建主键约束的语句添加到该字段的...
  • 如果你想指定一个其他名字的并且具有自动增长的主键,使用AutoField也是可以的。 2. BigAutoField 64位的整形,类似于AutoField,不过产生的数据的范围从1-9223372036854775807。 3. BooleanField 模型层面...
  • 我们知道MySQL表可以定义一个自增长的id,如果我们的没有指定主键字段,那MySQL会给我们的创建一个不可见的,长度为6个自己的row_id,然后不停地往上加步长,虽然生活自然数没有上限的,但是计算机里,...
  • 自动增长字段

    2018-10-22 02:34:00
    设计数据库的时候,有时需要的某个字段自动增长的,最常使用...MYSQL设定一个字段为自动增长字段非常简单,只要在表定义指定字段为AUTO_INCREMENT即可。比如下面的SQL语句创建T_Person,其中主键FId为自...
  • 1,高级数据操作2,查询数据3,查询中的运算符4,联合查询5,连接查询6,交叉查询7,内连接8.外连接9,using关键字高级数据操作新增数据多...主键冲突 主键冲突:有的表中,使用的业务主键(字段有业务含义),...
  • 很简单,现有一张商品(goods),里面有3个字段(id自增主键,name商品名字,price价格); 现在准备设计一张订单(order),要求一张订单可能包含一个或多个商品,而且商品数量不定,那么应该如何设计这个订单...
  • mysql字段约束

    千次阅读 2016-04-11 11:04:00
    主键是表的标志列,mysql支持将一个或多个字段作为一个主键来使用。关系数据库依赖于主键主键在物理层面只有两个用途: 唯一的标志一行记录 作为一个可以被外键引用的有效对象。 2>设置主键: 创建主键分为...
  • 主键: 约束 ... 是在一个字段上建立 一张表可以有多个唯一索引 不能作为外键 索引物理上存在的 mysql/sqlserver/oracle , 主键和唯一约束都会被自动添加唯一索引 参考: https://www.cnblogs.com/...
  • 似水晶报表的东西xtrareport中没找到啊,烦躁 这样的就不行,因为找ID 表中是不有相同或不同,如名字不同就找不出. 还有就是如果有一个表多一个记录,也算是两个表有不同记录 没有主键,...
  • 主键与索引

    2009-10-15 18:00:00
    区别:1:主键是为了标识数据库记录唯一性,不允许记录重复,且键值不能为空,主键是一个特殊索引.2:数据表中只允许有一个主键,但是可以有多个索引.3.使用主键会数据库会自动创建主索引,也可以在主键上创建索引,方便...
  • 主键和索引区别

    2008-05-27 23:19:39
    主键和索引两个概念 但当你建主键的时候,数据库会自动帮你建上索引 ...从数据库的应用来说, 每个表只可以有最多一个主键, 而表中其他的字段皆可以 用这个键为代表, 例如学生的注册纪录中,...
  • 如果从数据库索引优化角度看,使用InnoDB引擎而不使用自增主键绝对是一个糟糕的主意。 InnoDB使用聚集索引,数据记录本身被存于主索引(一颗B+Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存...
  • t_api_info 表,id为主键,自增字段,parent_id 是表中相同字段可以可以选关键得几,排序可要可不要) 实现:从t_api_info表中去重根据parent_id字段留下每组id最大得那条记录 DELETE FROM t_...
  • 自动增长字段 设计数据库的时候,有时需要的某个字段...MYSQL设定一个字段为自动增长字段非常简单,只要在表定义折定字段为AUTO_INCREMENT即可。比如下面的SQL语句创建Person,其中主键Fid为自动 增长字...
  • mysqlinnodb的存储引擎下使用B+树来做为索引的数据结构的,而一个表最终必定会创建一个主键索引,即没有设置主键也会有生成规则(先查找有没有非空的唯一索引,没有则可以使用默认的rowid字段创建索引) ...
  • 自动增长字段设计数据库的时候,有时需要的某个字段自动增长的,最常使用自动...MYSQL 设定一个字段为自动增长字段非常简单,只要在表定义指定字段为AUTO_INCREMENT即可.例子:createtablet_student ( t_idin...
  • 前言 主要使用到的技术:...可以向数据库中增加数据,但是主键id是一个长串的随机数。 二、问题分析 新创建一个数据库表,然后手动数据库表中添加数据时,字段的id值是正常的。但是只要一经过mybatisPlus操...
  • Oracle数据库实现字段自增

    千次阅读 2013-01-02 20:26:35
     用Oracle时,出现了这样一个状况,添加模块时,传入了一个模块名称,而表中还有一个模块ID,这个ID设定的自增。但是Oracle中没有字段自增这个功能。但是可以通过自己写序列、触发器来实现这样的一个功能。...
  • 设计三范式

    2016-11-14 07:51:34
    数据库设计三范式(nomorlization) 1NF:原子性,即每个字段都不可以分割了...3NF:一个表中不能包含其他表中已经存在的非主键字段信息,也就是说只可以包含其他表的主键信息,这样就是主外键,通过主外键就可以进行表
  • 数据库学习:关系

    2020-10-30 15:03:26
    一、关系表 两张表格,一张表的主键作为另一张表的外键,将两张表相互关联,利用外键可以查询到主键所在表的信息。...在一个表中,定义一个字段,这个字段中存储的数据时另外一张表中的主键 就是在
  • Django中,定义了一些Field来与数据库表中字段类型来进行映射。以下将介绍那些常用的字段类型。 AutoField: 映射到数据库中int类型,可以有自动增长的特性。一般不需要使用这类型,如果不指定主键,那么...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 184
精华内容 73
关键字:

在一个表中主键只可以是一个字段