在VirtualBox虚拟机中用IDA gdb debugger调试QEMU模拟器中的ARM程序
Haskell基础
Haskell Module
Haskell自定义数据类型
Haskell Guard
Haskell的基本定义
Haskell Tuple和模式匹配
列表概括记法
Haskell局部定义
Mono Sytem.Net
Virutalbox 端口映射
Nginx eCryptFs
解除ecryptfs
Python带星号的参数
表单中同名输入的处理
IDA Symbian调试
Carbide 调试
python中与时间相关的函数
5美元 512M VPS
在iPhone官方SDK中调用私有API
BlackBerry自动使用wifi连接的条件
郑重提示:本站投放的广告,很多有诈骗嫌疑,尤其是手机类, 医药类广告。本站所有内容,都不能作为投资或者消费的建议,请读者慎重行事。
Ubuntu的Desktop版本 默认已经安装好network-manager-gnome network-manager-pptp pptp-linux
但 network-manager-vpnc-gnome 可能没装上, 不过即使装上 vpnc-gnome , 连接时依然会提示 vpn服务没启动 (VPN service failed to start)
查看
/var/log/syslog 这个文件, 看到失败信息
nm_vpn_connection_connect_cb(): VPN connection ‘he’ failed to connect: ‘No VPN secrets!’.
connection_state_changed(): Could not process the request because no VPN connection was active.
奥秘就在 VPN 的设置中
0) 确认安装好了 network-manager-pptp
apt-get install network-manager-pptp
1) 不要选中 ” Available to all users” (对所有用户可用), 这个是最重要的
2) 授权方法要设置为 MSCHAPv2, 其他的PAP等方法都不要选
3) 对于he的VPN, 不支持加密, 所以不能选中 MPPE
4) 所有的压缩方法,都不要选 Allow BSD Data Compression , Allow Deflate Data Compression, Use TCP Header Compression
5) Send PPP Echo Packets 也不要选上
NetworkManager: Starting VPN service ‘org.freedesktop.NetworkManager.pptp’…
NetworkManager: VPN service ‘org.freedesktop.NetworkManager.pptp’ started (org.freedesktop.NetworkManager.pptp), PID 1683
NetworkManager: VPN service ‘org.freedesktop.NetworkManager.pptp’ just appeared, activating connections
NetworkManager: VPN plugin state changed: 1
NetworkManager: VPN plugin state changed: 3
NetworkManager: VPN connection ‘he’ (Connect) reply received.
NetworkManager: nm_vpn_connection_connect_cb(): VPN connection ‘he’ failed to connect: ‘No VPN secrets!’.
NetworkManager: connection_state_changed(): Could not process the request because no VPN connection was active.
成功的记录
NetworkManager: <info> Starting VPN service ‘org.freedesktop.NetworkManager.pptp’…
NetworkManager: <info> VPN service ‘org.freedesktop.NetworkManager.pptp’ started (org.freedesktop.NetworkManager.pptp), PID 1784
NetworkManager: <info> VPN service ‘org.freedesktop.NetworkManager.pptp’ just appeared, activating connections
NetworkManager: <info> VPN plugin state changed: 1
NetworkManager: <info> VPN plugin state changed: 3
NetworkManager: <info> VPN connection ‘he’ (Connect) reply received.
pppd[1786]: Plugin /usr/lib/pppd/2.4.5//nm-pptp-pppd-plugin.so loaded.
pppd[1786]: pppd 2.4.5 started by root, uid 0
NetworkManager: SCPlugin-Ifupdown: devices added (path: /sys/devices/virtual/net/ppp0, iface: ppp0)
NetworkManager: SCPlugin-Ifupdown: device added (path: /sys/devices/virtual/net/ppp0, iface: ppp0): no ifupdown configuration found.
pppd[1786]: Using interface ppp0
pppd[1786]: Connect: ppp0 <–> /dev/pts/1
pptp[1790]: nm-pptp-service-1784 log[main:pptp.c:314]: The synchronous pptp option is NOT activated
pptp[1797]: nm-pptp-service-1784 log[ctrlp_rep:pptp_ctrl.c:251]: Sent control packet type is 1 ‘Start-Control-Connection-Request’
pptp[1797]: nm-pptp-service-1784 log[ctrlp_disp:pptp_ctrl.c:739]: Received Start Control Connection Reply
pptp[1797]: nm-pptp-service-1784 log[ctrlp_disp:pptp_ctrl.c:773]: Client connection established.
pptp[1797]: nm-pptp-service-1784 log[ctrlp_rep:pptp_ctrl.c:251]: Sent control packet type is 7 ‘Outgoing-Call-Request’
pptp[1797]: nm-pptp-service-1784 log[ctrlp_disp:pptp_ctrl.c:858]: Received Outgoing Call Reply.
pptp[1797]: nm-pptp-service-1784 log[ctrlp_disp:pptp_ctrl.c:897]: Outgoing call established (call ID 0, peer’s call ID 2816).
pppd[1786]: CHAP authentication succeeded
pppd[1786]: Cannot determine ethernet address for proxy ARP
pppd[1786]: local IP address 188.189.186.111
在Debian Squeeze, Ubuntu Lucid 中 安装增强包(Guest Additions)
apt-get install virtualbox-ose-guest-x11
否则,你的Ubuntu客户机 桌面系统 只有 800×600的分辨率
如果使用SSH协议,格式为
git clone ssh://worker@zhiwei.li/home/zhiwei/text/
其中zhiwei.li为 主机的域名, 或者IP 地址
后面接着 从 该系统中,工程所在的绝对路径(也就是从 根目录 开始)
另外一种格式就是
git clone worker@zhiwei:/home/zhiwei/
这是遵循 sftp 客户端的表示方法
sftp [user@]host[:dir[/]]
据说 git clone ssh://user@server:project.git
和 git clone user@server:project.git
都是可以的, 如果不证明协议,默认就使用SSH
对于HTTP和GIT协议,格式与SSH的第1种格式类似
加州理工经济学教授R. Preston McAfee写的一本微观经济学教材,版权采开源形式,只要不用于商业用途,可随意翻译、改编、发表。作者希望此书可以有中文版,免费供中国的学生和老师使用。
来源: http://article.yeeyan.org/view/169041/127699
译者 : eric0812
1.经济学是什么
经济学研究稀缺资源在社会中的分配问题,分析何种产品和服务最终分配到哪些人手里。为何研究稀缺资源?如果资源不稀缺,就不存在有效分配的问题了。经济学家研究所有实际的和许多不切实际的稀缺资源分配方式。由于市场是一种非常重要的资源分配手段,所以经济学家(通过)研究市场(来研究资源分配)。市场包括股票市场(如纽约证券交易所)、商品市场(如芝加哥商品交易所)、农贸市场、拍卖市场(如佳士得或索斯比拍卖行——电影里面人们想方设法通过它们购买中国明代瓷瓶,使这些拍卖行一举成名、Ebay或其他更加临时性的市场——如小区内的音乐唱片市场)。除此之外,政府也通过税收参与商品和服务等稀缺资源的分配。政府可以通过某种政治进程来控制,由政策主导分配的研究被称为政治经济学,它是经济学的一个重要分支。商品通过特定的方式进行分配,如偷窃、被政府认定为非法所得,这种分配方式仍然是经济分析的研究领域;尽管多数国家的政府禁止大麻交易,但大麻市场仍然繁荣。其他分配方式还包括赠送、慈善捐助、彩票中奖、赌博、合作社,这些都是经济学家的研究对象。
有些市场涉及有形市场。纽约证券交易所的交易者在交易厅进行交易,Ebay用户在电子市场进行交易。还有一些市场,我们就更熟悉了。这些市场中有实体店铺,或聚集,或分散,顾客在商店中挑选、购买质量和价格合适的商品。我们买香蕉时,不必专门跑去香蕉市场,去杂货铺买就行了。然而,当我们买香蕉时,这些杂货铺的确是在竞争,吸引顾客前往,并诱使他们购买香蕉。
价格——用货币交换商品和服务——是一种非常重要的分配手段,但绝不是唯一的手段(即使在市场交换中也不是)。影响分配的其他条件还包括(得到商品或服务)的便利性、信誉、可信度,这些条件在交易中同样有其价值。某些市场上的产品,如索尼36英寸WEGA电视、奇多食品、福特-奥拓雷特火花塞,销售这些产品的经销商很多,但产品品质完全相同。对于这些产品,价格往往是购买者考虑的首要因素,尽管别的交易条件如运输对人们的购买决策也起作用。对于其他商品,如宾馆的饭菜、不同厂家生产的摄像机、不同航线的飞机票,产品差别较大,所以,产品质量往往成为购买者考虑的因素。然而,即使是不同的商品,只要这些商品在某种程度上具有可替代性,也可以放在同一个市场上比较,对于这种商品,我们可以考虑使用“质量调整价格”进行比较。
经济分析被用于很多场合。如果英国石油公司要为它的阿拉斯加原油定价,它会使用一种需求估计模型,评估汽油消费者和它的原油精炼厂顾客。石油精炼厂使用一种复杂的经济模型来管理他们的石油需求,而英国石油公司则使用这种模型来估计石油精炼厂的石油需求。在美国司法部提起的反垄断诉讼中,专家们则利用这些模型分析微软将它的竞争对手Netscape公司驱逐出市场的动机,以及消费者在面对他们的抵押权可能会遭到剥夺时所采取的行为。股票市场专家使用经济模型分析公司利润,以便预测股票价格。政府做财政预算或考虑修改环境法规时,会使用多种经济模型。本书将呈现给读者大量经济学家日常使用的许多基础经济学模型。
1.1.1 规范理论和实证理论
经济分析的用途主要有两种。第一种用途是科学理解商品和服务等稀缺资源的分配如何决定。就像电磁学和分子生物学一样,实证分析仅仅试图解释周围的世界。然而,随着实证理论的发展,实证分析在经济学上还有其他用途。经济分析能够证明法律法规的变动和政府介入市场会影响人们生活,在某些情况下,我们可以得出结论:总的来说,改变规则对社会有益。规范分析和实证分析一起使用,预测改变规则产生的后果,并且加入价值判断。例如,为修建高速公路而征收汽油税,这一方面损害了汽油消费者的利益(因为他们要出更高的价钱购买汽油),另一方面则有利于汽车驾驶员(因为不仅路面不会像以前那样坑坑洼洼,而且堵车也减少了)。不过,总体来看,汽油消费者和汽车驾驶员是同一个群体,规范分析能够证明,每个人都会受益。由于改变了规则,每个人都能得益。对于这种产出模型,相对来说没有多少争议。
相比之下,成本-效益分析则通过比较不同人群的获益和损失,提出改变规则的对策,使收益大于损害。例如,某地为修建公园而征收财产税,使用公园的人将因此获益,而拥有财产的人则会受损(尽管随着财产的增值,即是不使用公园的人也会获得一些好处)。既然有些纳税者不会使用公园,这就不是一条总体上使每个人获益的政策。成本效益分析根据收益权衡成本。在修公园这个案例中,由于成本等于税收,所以成本是确定的。相比之下,计算收益更加困难。理论上来说,如果公园收费的话,收益就等于公园的使用者愿意为使用公园而付出的价钱。然而,如果公园不收费,我们就只能估算“使用者愿意付多少钱”了。基本上,如果公园给使用者带来的收益大于给纳税者带来的损失,我们就说公修建公园的效益大于成本。但是,其中仍然涉及利益在不同群体间的转移。
福利分析为我们提供了另一种方法,计算政府介入市场而产生的后果。福利分析假定社会性的偏好和目标,如帮助穷人。总体上来说,福利分析当中也涉及成本-效益分析,但它考虑的不仅仅是总体上的收益和成本,也权衡这些收益和成本可能给其他社会群体带来的影响。例如,为补贴剧院而征收财产税,其总体收益可能大于成本,但是财产税的纳税主体是中低收入者,而去剧院看戏的多数都是富人。这样一来,剧院补贴就使得财富从低收入者转移给了高收入者,这不符合社会公平的目标。相比之下,取消对日常食品,如牛奶、面包的销售税,总体上对穷人有益,因为穷人在食物上的花费占他们收入的比例,比富人高得多。这样看来,这项计划的诱人之处并不在于它所带来的整体收益,而在于重新分配收益。经济学不仅提供分析税收等政策的整体影响的分析工具,还分析税收和政策所带来的社会影响,那就是,哪些人受益,哪些人买单。哪些事是经济学家无能为力的呢?那就是:谁该得益,谁该受损。那些事就交给社会学家来决定吧。
1.1.2 机会成本
经济学家所讲的成本也许有点古怪,不过你稍加思考就会明白,我们使用机会成本这种奇怪的概念来表示成本。对经济学家来说,成本不仅仅是为购买一件物品而付出的现金,而是他在购买过程中所放弃的所有价值的总和。比如,上大学的成本包括学费、书费,还有如果你不上大学,能够挣到的工资。其实,为接受大学教育而付出的时间也是成本的一部分(因为读大学,你放弃了那么多娱乐活动)。然而,在我看来,“成本”却不一定就是机会成本。宿舍和伙食一般不被视为成本,因为不管上不上大学,你都要吃饭、住宿。只有当大学里的宿舍和伙食比外面贵时,它们才计入成本。同样地,如果不上大学,你可能会花钱去学习滑翔,去欧洲旅行,这部分费用可视为节省。尽管如此,忙于阅读此书时,你的确浪费了这些活动带给你的价值。
机会成本的概念可以用一句定义概括。
机会成本就是为了得到一种价值而放弃的其他可以得到的最大价值。
这个定义充分表达了成本的概念,即成本不单单是为得到一件东西而花费的金钱,还包括为了得到这件东西,你放弃的价值。花17美元买一张CD的机会成本,就是你用这17美元所能做的其他事情,或许还有你购物所花费的时间价值。养狗的机会成本不单单是买狗所花的费用,还包括狗粮、请兽医、清洁地毯,和花费在遛狗上的时间。在解释机会成本时,养狗是个很好的例子,因为在养狗的机会成本中,买狗所花的费用只占很小一部分,可忽略不计。尽管养狗成本很高,人们还是一直在养。为什么呢?从经济学的视角来看,人们之所以养狗,是因为人们期望从中得到的回报大于机会成本。也就是说,当人们觉得狗狗的价值大于他们能够用同样的金钱购买到的其他物品时,他们就会养狗。
尽管机会成本包含许多非货币投入,我们往往将其转化为货币投入,以便比较。显然,将机会成本货币化有其价值,因为这样提供了一种比较的方法。蹲30天监狱的机会成本是什么?那些被宣判有罪的被告往往被问到“30天拘留还是付30美元”之类的问题,让这些被告自己选择。理论上来说,我们也可以使用同样的方法确定“30天监狱生活”的价值究竟有多少。设想你选择付750美元以避免牢狱之灾,但是如果让你付1000美元,你宁愿选择进牢房。那么,30天监狱生活的价值就介于750美元和1000美元之间。基本上来说,存在这样一个价格,在不超过这个价格的时候,你愿意接受付款;而如果超过这个价格,哪怕超过一分钱,你也宁愿选择坐牢。你愿意为躲过牢狱之灾而付出的费用就是用货币表示的坐牢成本。
应用在上述选择坐牢和接受罚款之中的理论还可以在其他方面解释货币化的机会成本。比如,任何赌博都存在一个资本回收保证量,相对于这个特定的量,一个人愿意选择去赌博。实际上,任何企业都在购买或销售风险,而风险控制领域的很大一部分都涉及购买或销售有风险的项目,以降低风险。在这个过程中,风险被赋予了价值,风险股票和资产只能以较低的价位出售(或者说,获得较高的平均收益)。这种差价被称为风险溢价,它表示在一场存在风险的赌博中,其风险部分被货币化表示了。
购房者在购房时总要面临多种选择,如选择一楼还是二楼,砖质结构还是木质结构,天花板材料、木质地板还是铺地毯,带不带游泳池,视野怎么样,是否靠近公园,等等。评估这些东西的价值的方法被称为“快乐定价理论”,先单独评估每件东西的价值(如:游泳池会带来怎样的收益?),然后将每个部分的价值加总。同样的方法也被用于评估旧车价值,首先给出一个基准值,然后在这个基准值的基础上根据车内非必须物品的多少(如有没有黑色皮座套、CD开关等)来调整价格。我们再一次使用这种估价方法将一堆完全不同的零件转化成了货币价值。
很多时候,完全用货币表示成本的方法有很大的争议,尤其是在评价人的生命的价值时。你的生命值多少钱?能用货币表示吗?我们可以利用风险来解答这个问题。开车时系上安全带,并在车上配备额外的安全设备能够降低死亡风险,尽管只能降低很小一部分,但这种降低的风险却是可以计算的。假设一个400美元的安全气囊能够从总体上降低0.01%的死亡风险,如果你愿意购买安全气囊,那么其实你已经计算出了死亡风险的价值,那就是:0.01%的死亡风险值400美元,1%就是40,000美元,或者说100%死亡就是4,000,000元。当然,你会发现0.01%和100%的死亡概率天差地远,因为100%就意味着你必死无疑。但是这种方法的确提供了一种估计死亡风险价值的方法——计算人们为了降低风险,愿意(或不愿意)付出什么。
机会成本——为了得到一种价值而放弃的其他可以得到的最大价值——是经济分析的基石。用货币方式表示成本为我们提供了一种比较成本的方法,尽管这种方法尚存争议。
首先设置环境
%comspec% /k “”e:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat”" x86
cmd /k “e:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat“ x86
然后用csc.exe编译
csc hello.cs
下面提供我收集的一些简单的UI Control
//A very simple checkbox
using System.Windows.Forms;
class test : Form //class test inherit from the class Form
{
public static void Main()
{
test HelloForm = new test();
HelloForm.BackColor = System.Drawing.Color.Yellow; //set the color of the form
System.Windows.Forms.CheckBox check = new System.Windows.Forms.CheckBox();
HelloForm.Controls.Add(check);//Attach CheckBox to the Form
Application.Run(HelloForm);//display form
}
}
存为 checkbox.cs
编译 csc checkbox.cs
//A very simple form
using System.Windows.Forms;
class test : Form //class test inherit from the class Form
{
public static void Main()
{
test HelloForm = new test();
HelloForm.Text = “How do you do?”;//specify title of the form
Application.Run(HelloForm);//display form
}
}
文本输入
//A very simple form with attached textbox
using System.Windows.Forms;
class test : Form //class test inherit from the class Form
{
public static void Main()
{
test HelloForm = new test(); //create form
System.Windows.Forms.TextBox text = new System.Windows.Forms.TextBox(); //create textbox
text.Text = “This is a textbox”;// Specify default text to be displayed inside TextBox
HelloForm.Controls.Add(text);//Attach TextBox to the Form
Application.Run(HelloForm);//display form
}
}
下面这个是button
using System;
using System.Drawing;
using System.Windows.Forms;
public class HelloWorld : Form
{
static public void Main()
{
Application.Run(new HelloWorld());
}
public HelloWorld()
{
Button b = new Button();
b.Text = “Click Me!”;
b.Click += new EventHandler(Button_Click);
Controls.Add(b);
}
private void Button_Click(object sender, EventArgs e)
{
MessageBox.Show(“Button Clicked!”);
}
}
稍微复杂一些的
using System;
using System.Drawing;
using System.Windows.Forms;
namespace MyNamespace
{
class HelloWorldForm : System.Windows.Forms.Form
{
Label lblHello;
Button btnClose;
public HelloWorldForm()
{
this.Text = “Hello World Sample”;
btnClose = new Button();
lblHello = new Label();
btnClose.Click += new EventHandler(btnClose_Click);
btnClose.Text = “Close”;
btnClose.Location = new Point(10, 100);
btnClose.Size = new Size(200, 50);
lblHello.Text = “Hello World!”;
lblHello.Location = new Point(10, 10);
lblHello.Size = new Size(200, 50);
SuspendLayout();
this.Controls.Add(lblHello);
this.Controls.Add(btnClose);
ResumeLayout(false);
}
void btnClose_Click(object sender, EventArgs args)
{
this.Close();
}
[MTAThread]
static void Main()
{
HelloWorldForm mainForm = new HelloWorldForm();
Application.Run(mainForm);
}
}
}
下载这个是用wizard生成的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
public class Form1 : Form
{
private TextBox textBox1;
public Form1()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.AcceptsReturn = true;
this.textBox1.AcceptsTab = true;
this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBox1.Multiline = true;
this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
//
// Form1
//
this.ClientSize = new System.Drawing.Size(284, 264);
this.Controls.Add(this.textBox1);
this.Text = “TextBox Example”;
this.ResumeLayout(false);
this.PerformLayout();
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
SELECT * FROM Subscription group by IMEI having count(*) >=2;
选出的记录都是后插入数据库的记录
如果同时需要两个column的值都一样
SELECT * FROM Subscription GROUP BY IMEI, OrderId HAVING count(*) > 1;
选出重复的记录
SELECT * FROM Subscription WHERE IMEI IN (SELECT IMEI FROM Subscription GROUP BY IMEI HAVING count(*)>1);
SELECT * FROM Subscription WHERE IMEI IN (SELECT IMEI FROM Subscription GROUP BY IMEI HAVING count(*)>1) AND Status=2;
选出重复记录中rowid最大的那些(SQLite)
SELECT * FROM Subscription WHERE IMEI IN (SELECT IMEI FROM Subscription GROUP BY IMEI HAVING count(*) >1)
AND rowid NOT IN (SELECT max(rowid) FROM Subscription GROUP BY IMEI HAVING count(*) >1);
删除上面选出来的记录
DELETE FROM Subscription WHERE IMEI IN (SELECT IMEI FROM Subscription GROUP BY IMEI HAVING count(*) >1)
AND rowid NOT IN (SELECT max(rowid) FROM Subscription GROUP BY IMEI HAVING count(*) >1);
为表单动态添加或者删除输入元素, 可以使用javascript的appendChild或者removeChild
start<input name=”start” id=”startid” type=”text” size=”2″ value=”1″>
count<input name=”count” id=”countid” type=”text” size=”2″ value=”2″>
<form action=”b.php” method=”post” id=”deleteform” name=”deleteform” >
<input name=”eventid” id=”eventid” type=”hidden” value=”1,2″>
</form>
<button onclick=”DeletePage();” >Delete Page</button>
<script type=”text/javascript”>
function DeletePage()
{
var deleteform = document.getElementById(‘deleteform’);
deleteform.action = ‘delete_page.php’;
var startinput = document.getElementById(’startid’);
var countinput = document.getElementById(‘countid’);
var eventinput = document.getElementById(‘eventid’);
alert(deleteform.length);
//var element = document.createElement(“input”);
//element.setAttribute(“type”, ‘text’);
//element.setAttribute(“value”, ‘big’);
//element.setAttribute(“name”, ‘g8′);
//deleteform.appendChild(element);
deleteform.appendChild(startinput);
deleteform.appendChild(countid);
deleteform.removeChild(eventinput);
alert(deleteform.elements.length);
deleteform.submit();
}
</script>
直接给form[0] 赋值,不能成功, 必须使用appenChild
我尤其关心的是 在UNIQUE列中是否可以插入多个NULL值
答案是:
为了跟其他数据库系统(如PostgreSQL, MySQL, Oracle) 保持一致, NULLs 在 UNIQUE列是不同的, nulls are distinct in a UNIQUE column
请参考 http://www.sqlite.org/nulls.html 的表格
在微软的MSSQL 的方法是, 不要使用UNIQUE约束, 而是使用UNIQUE索引
The UNIQUE constraint causes an unique index to be created on the specified columns. All NULL values are considered different from each other and from all other values for the purpose of determining uniqueness, hence a UNIQUE column may contain multiple entries with the value of NULL.
UNIQUE约束会在指定的列 创建一个unique索引. 所有的NULL值被认为 彼此不同,并且跟其他非NULL值也不同, 从而决定了其唯一性. 所以,在一个UNIQUE列可以含有多个NULL条目
来自wikipedia
http://en.wikipedia.org/wiki/Candidate_key
http://zh.wikipedia.org/zh-cn/%E5%80%99%E9%80%89%E9%94%AE
在数据库的关系模型中,候选键是某个关系变量的一组属性所组成的集合,它需要同时满足下列两个条件:
1) 这个属性集合始终能够确保在关系中能唯一标识元组
2) 在这个属性集合中找不出合适的子集能够满足条件(1)
满足第一个条件的属性集合称为超键,因此我们也可以把候选键定义为“最小超键”,也就是不含有多余属性的超键。
候选键的重要性是它们能够在关系中唯一标识出不同的元组,因此超键也是在设计数据库模式时需要指定的最重要的约束之一。由于在关系模型中,每个关系都是一个集合(没有重复的元素),所以每个关系都至少有一个候选键(因为所有属性组合必然是个超键)。但是在某些关系型数据库中表也能代表多重集,所以在每个关系中都显式地定义至少一个候选键是一条很重要的设计原则。数据库管理系统通常都需要将每个关系中的某个候选键定义为主键,亦即这个候选键是区分不同元组时首选的识别方式,例如外键通常就是引用主键而非其他候选键。