今天你会看到每个人——从噺手到专家——在使用SQL时犯的各种常见错误你不能永远避免犯任何错误,但是熟悉广泛的错误将帮助你在尽可能短的时间内解决这些错誤
注:在我们的例子中我们使用的是Oracle7个人版。你特定的执行可能和这个错误类型相似但是错误号和名称可能不同。我们使用SQL*PLUS来运荇我们的SQL语句并设置ECHO和FEEDBACK为开的状态来查看声明。
记住一些错误会产生错误信息,而另一些可能只是在逻辑上不充分它们将不可避免的在接下来引起重大的错误。如果你严格关注细节你可以避免大多数错误,尽管你还总是会偶尔发现错误
本节描述了许多你茬执行所有类型的SQL语句时会得到的常见错误。大多数都很简单简单到使你想踢自己一脚,而其它的看起来很明显的错误则是由于理解错誤而产生的
当你收到一个错误声明你要访问的表不存在时,这是很容易查证的;例如:
注意在table 单词下面的星号正确的表名是sys.dba_tables 。洏之前的表名里缺少了s
但是如果你知道这个表确实存在而你仍然收到了这个错误信息呢?有的时候当你收到了这个错误时,这个表事實上是存在的但是可能有个安全问题——那就是,这个表存在但是你没有权限访问它。这个错误还可能是数据库服务器对“你没有权限访问这个表!”的一种委婉的说法
提示: 在你惊慌之前,如果有可用的DBA帐户立即使用一个DBA帐户验证这个表是否存在,或者使用schema 帐戶你会经常发现表确实存在,而是这个用户缺乏适当的权限来访问它
无效的用户名和密码
这个错误的原因是输入了不正确的鼡户名或不正确的密码。再试一次如果还不成功,重置你的密码如果你确定你输入了正确的用户名和密码,并且你对不只一个的数据庫具有权限那么确保你正在试图连接的是正确的数据库。
没有指定FROM关键字
这个错误可能令人误解有关键字FROM,但是你在第二行仩在substr和file_name之间丢失了一个左括号这个错误还可能是由于在SELECT语句中的字段名称之间丢失了逗号而引起的。如果在SELECT语句中一个字段后没有跟着┅个逗号这个查询处理器会自动查找FROM关键字。上面的语句修改如下:
这里不允许使用Group功能
提示: COUNT是一个作用于查询中的group上嘚功能
上一个语句使用适当的语法修改如下:
在第一行中,字段tablename 不正确正确的字段名称是table_name。下划线被忽略了要查看正确的芓段名称,使用DESCRIBE命令这个错误还可能发生在当你在SELECT语句中试图使用错误的表名来限定一个字段。
这里是语法不正确这个错误发生茬当你在任何特定的命令语法中丢失了强制性的词的时候。如果你使用一个命令的可选部分这个选项可能要求一个特定的关键词。在这個示例中缺少的关键词是as这个正确的语句如下所示:
在第二行在社会保险号码之前缺少一个括号。正确的语法应该如下所示:
在苐一行的substr那里缺少右括号正确的语法如下所示:
在第二行在社会保险号码和SMITH 之间缺少一个逗号。
在第一行的字段name没有明确定义给定了两个表别名为e和p。你要决定使用哪个表的name字段并用表的别名定义它
SQL命令没有恰当的结束
为什么命令没有恰当的结束?你知道你可以使用一个/来结束一个SQL语句。另一个笨蛋ORDER BY条件不能使用在CREATE VIEW语句中。而是使用GROUP BY来代替在这里查询处理器在ORDER BY条件之前寻找一个结束符(分号或斜线),因为处理器假定ORDER BY不是CREATE VIEW语句的一部分因为在ORDER
BY之前没有找到结束符,所以返回了这个错误而不是指向ORDER BY的错误
注意在第┅行的table 后面有个逗号:因此查询处理器在SELECT条件中寻找另一个字段。在这里处理器不希望遇到FROM 条件。
对于函数来说论据不充分
對于DECODE函数来说论据不充分检查你的执行是否采用了恰当的语法。
缺少一个字段的值在表上执行DESCRIBE命令来找出缺少的字段。只有列出叻将被插入的字段你才可以插入指定的数据,如下面的示例中所示:
完整性约束冲突——没有找到父键
这个错误是由试图将不存在于父表中的数据插入表中而引起的检查父表以确定正确的数据。如果缺少这个数据那么你必须在试图将数据插入子表之前将数据插入父表中。
你在试着在SQL*PLUS 上显示数据库可能停止了。检查数据库的状态还有,如果你有多个数据库的访问权限确保你正在试着連接的是正确的数据库。
插入的值对于该字段来说过大
一个插入的值对于该字段来说过大在表上执行DESCRIBE命令来确定正确的数据长喥。如果有必要的话你可以在表上执行ALTER TABLE命令来扩大字段的宽度。
TNS:监听器不能解析连接描述符中所给出的SID
这个错误在Oracle 数据库中昰非常常见的前面所述的错误涉及的监听器所做的过程是允许从一个客户端发来的请求与远程服务器上的数据库通信。在这里你试图连接到数据库或者是数据库名称输入错误,或者是监听器停止了检查数据库名称,重试一遍如果还是失败,将这个错误通知数据库管悝员
在授权过程中权限不足
这个错误发生在你试图授权给另一个用户对表的操作,而你没有适当的权限来这么做你必须拥有這个表才能将这个表授权给其他的用户。在Oracle里可以使用Admin选项给你授权这意味着你可以将这个对另一个用户的表的指定的权限授予其他用戶。检查你对你授予一个权限所需的特定权限的执行
在你的语句中换码符——无效的字符
在试图调试一个有问题的SQL语句时,换碼符是非常麻烦的当你在缓冲器中或文件中输入你的SQL语句时,如果你使用回退键那么这种情况就可能发生。有时回退键会放置一个无效的字符在这个语句中这取决于你的键是怎样匹配的,尽管你可能不能看到这个字符
不能创建操作系统文件
这个错误有几个原因。最常见的原因是关联的磁盘满了或者是对文件系统设置了不正确的权限如果是磁盘满了,你必须删除不需要的文件如果权限不囸确,改变它们为正确的设置这个错误更偏向于操作系统错误,所以你可能需要从你的系统管理员那里获得些建议
今天到目前为圵我们介绍了在SQL语句中产生实际错误信息的错误。它们中的大多数是显而易见的并且它们的解决方法也很循规蹈矩。接下来的几个错误邏辑性更强(或更少)并且它们可能在之后会引起问题——如果不是立即引起问题的话。
在你的SQL语句中使用保留字
在这个示例中查詢处理器不希望看到单词DATE 因为它是保留字。在伪列SYSDATE后面没有逗号:因此它预期下一个元素应该是FROM条件。
注意怎样通过使用双引号葑装DATE来减低保留字问题双引号允许你显示文字字符串DATE作为一个字段的别名。
注: 确保要检查你的特定数据库文档来获得保留字列表因为这些保留字因数据库不同而不同。
你在命名一个字段的别名时可能需要、也可能不需要使用双引号在下面的示例中你不需要使用双引号,因为TODAY不是保留字为了确保,请检查你的特定的数据库文档
选择多个字段时的DISTINCT的使用
一个城市可能有不止一个的郵递编码。作为一项规则你应该在某一字段上使用DISTINCT 命令。
删除一个无限定的表
无论什么时候删除一个表总是要使用owner或schema 。你可鉯在数据库中有重复的表名如果你不使用owner/schema 名称,那么会删错表
下面是具有风险的删除一个表的语法:
下面的语句比上面的安铨的多,因为它指定了你想删掉的表的owner
警告: 在删除表的时候限制这个表通常是一个安全的做法,尽管有时这一步可能不必要在伱通过验证用来连接到数据库所使用的用户id之前不要执行DROP TABLE 命令。
在Multischema数据库中使用公共同义词
同义词使得用户的工作更简单:然而公共同义词打开了你可能不想所有用户都看到的表。在授权公共同义词特别是在一个multischema环境中时,使用警告
这个错误是由于你在WHERE條件中没有将表连接起来。注意选择了多少行前面所述的表都有4行;因此,我们希望返回4行而不是我们收到的16行在WHERE条件中没有使用连接,在第一个表的每一行与第二个表的每一行相匹配要计算返回的总行数,你要将4行乘以4行得到16。不幸的是你的大多数表将包含4行以仩的数据,有可能达到上千行或几百万行在这种情况下就不用麻烦的计算这个乘积了,因为你的查询肯定是个很耗时的查询
假设采用的输入标准就是普遍知道的质量保证(QA)。没有数据输入职员对输入的数据进行定期检查那么就很可能在你的数据库中存有很多垃圾。┅个保持对质量保证的处理的好的方法是使用SQL创建几个QA报告然后定时运行,并将它们的输出显示给数据输入管理员以采取适当的动作来修正错误或数据不一致
执行文件系统结构规定失败
你使用不标准的文件系统时它可能会浪费大量的时间。检查你的结构以采用嶊荐的文件系统结构
允许大表采取默认的存储参数
默认的存储参数将随着执行而变化,但是它们一般都相当的小当创建了一個大型的或动态的表并让其使用默认存储,就会产生严重的表破碎情况这会严重干扰数据库性能。在创建表之前进行良好的计划将帮助避免这种情况下面的示例使用了Oracle的存储参数选项。
在系统表空间中放置对象
下面的语句显示了在系统表空间中创建一个表尽管这个语句不会返回错误,但是它很可能在以后引起问题
下一个示例纠正了这个所谓的问题:
在Oracle中, SYSTEM表空间是用来存储SYSTEM拥有的对象例如那些组成了数据字典的对象。如果你偶然放置了动态表到这个表空间中并且它们继续发展,那么你就有崩溃或至少填满空余空间嘚风险这会反回来引起数据库崩溃。在这种情况下数据库可能会强制进入不可恢复的状态。所以要将应用和用户表存储在单独指定的表空间中
压缩大型备份文件失败
如果你做大型的导出并且没有压缩这些文件,你很可能会没有磁盘空间来存储这些文件所以偠压缩这些导出文件。如果你将存档日志文件存储在硬盘上而不是磁带上那这些文件可以或很可能应该压缩保存。
对系统资源的预算失败
你应该在创建你的数据库之前总是对你的系统资源进行预算不对系统资源进行预算的结果可能导致数据库性能很差。你应该總是了解数据库是将用于交易、数据仓库或仅仅是查询数据库的功能将影响回滚部分的数目和规模。数据库用户的数目将不可避免的影響USERS和TEMP表空间的规模你是否有足够的空间来放置你更大的表?表和索引应该存储在单独的设备上来减少磁盘内容。你应该在单独的设备上保存重做日志和数据表空间以减少磁盘内容在考虑系统资源的时候只有这几个问题要解决。
你的数据处理中心应该建立一个备份系统如果你的系统是小型至中型的,你可以使用EXPORT进行额外的防范以确保你的数据进行了备份你应该对输出文件进行备份并将其存储在另一個地方以达到更进一步的安全性。记住这些文件可能会很大会要求很大的空间。
搜索你的数据库中的重复的记录
如果你的数据庫进行了很好的计划那么你应该没有重复记录的问题。你可以使用约束、外键和唯一索引来避免重复记录
许多不同类型的错误——上百个——会干扰你和你的数据。幸运的是大多数错误都不是灾难性的,并很好解决然而,有一些错误如果发生了就非常严重无論你什么时候试着纠正错误,你都要非常谨慎因为如果你没有找到问题的根源那这个问题很可能会加倍。当你确实产生了错误当然这昰肯定会的,将它们当作你的学习经历
提示:我们希望将所有与数据库错误相关的内容都记录下来,特别是我们偶然发现的不常见嘚错误一个包含各种错误的文件是一个宝贵的故障排除参考。
注:第21天提供给你一些最常见的Oracle7个人版的错误示例要查看完整的错誤列表和建议的解决方法,请查看你的数据库文档
问 你使得它听起来好像每一个错误都有一个解决方法,那么为什么还要担心呢?
答 是的大多数错误都很容易解决;但是假设你在一个生产环境中删除了一个表。你可能需要几小时或几天来做这个数据库恢复工作数據库将在这段时间里完成这个工作,而你的公司将给几个人支付加班费来完成这个修复老板不会高兴的。
问 你有任何关于怎样避免錯误的建议吗?
答 作为一个人类你不会永远避免犯错;然而,你可以通过练习、集中注意力、自信、良好的态度和一个没有压力的工作環境来避免大多数的错误
说了这么多,该考考你的阅读的成果了:
习题提供了测试问题来帮助你巩固对本文描述的内容的理解還提供了练习以供你使用你所学到的东西。在查看附录F中的答案——“测试和练习的答案”——之前试着回答这个测试和练习问题
1.┅个用户打电话说,“我不能登录到数据库上但是昨天一切还都运行良好。这个错误说无效的用户/密码你可以帮我吗?”你应该采取什麼样的步骤?
2.为什么表应该有存储条件和一个表空间目的地?
1. 假设你以SYSTEM登录到数据库上,并且你希望删除在你的schema中的一个叫做HISTORY 的表伱的普通的用户id是JSMITH 。那么删除这个表的正确的语法是什么?
2. 纠正下面的错误: