[翻译]在论坛上怎么贴数据和脚本才能得到最好(最快)的帮助

bwu851 2008-07-03 12:29:05
在论坛上怎么贴数据和脚本才能得到最好(最快)的帮助 (part one)

首先感谢pureaqua同学帮我校稿和润色, 才使我能较早的把此文贴出来.

不知道发在这儿行不行. 主要是讲我们SQL的, 所以就先发这儿吧. 其实此文对别的提问题贴都合适的. 版主看在哪儿合适, 可以转过去. 谢谢.

在这个论坛不长的时间里看到好多象这样的贴子: "我连不上SQL SERVER了. 急!! 请高手/专家帮忙!!!"
每次看到这样的贴子, 就觉得不知说什么好了. 我肯定回贴的有N种说法. 这样很浪费大家的时间, 主要是耽误了发贴者自己的时间.
而发贴者本来是想尽快解决的 (除非是故意消遣大家). 如果你能把错误信息和你的环境说清楚, 那么回贴的就可以更有针对性了.
(例如你说: 我的SQL Server 2005 EE + SP2 + Windows 2003 SP2 + 域. 现在出现了 -- 连接失败, 请查SQL Server注册信息 ---的错误.)
这样一说是不是清楚很多呀?


前两天在一国外论坛上发现一篇讲怎么问问题的文章, 感觉不错, 给大家翻译看看,献丑了。
**************************************************************************************
论坛的礼仪: 在论坛上怎么贴数据和脚本才能得到最好(最快)的帮助

前言
当你碰到T-SQL的问题时, 你很想有人能帮你一把. 于是就进了一个著名的网站, 如, bbs.csdn.net, 你知道在那儿有很多高手/专家会很快对你的问题感兴趣并会帮你解决. 你马上把你的表结构和数据贴了上去, 并且自以为已经很好的描述了你的问题和你想得到的结果.....

但是, 过了几小时, 甚至几天, 你的贴子都没人回. 在你老板的压力和很绝望的情况下, 你可能会使用两种在各种论坛中最不齿的行为: 重复发贴和自己"顶"贴.........

然而,当终于有人回答你绝望的求助时却发现别人给你的代码是错的, 甚至更糟的是只给个很闹心的建议而不是经过测试并能解决你的问题的代码.

那么问题在哪儿呢?
大多数情况是你贴数据或代码的方法错了


贴数据的错误方法
一般情况下, 当某人贴上一个诸如"我有个含如下的数据的表"的贴子时, 他(她)就会贴出下面数据:(这只是600多实际数据中的前8个)

ID DateValue Value YearValue Monthvalue
4 2007-10-17 00:00:00.000 5.1709 8 1
37 2007-10-17 00:00:00.000 5.5319 17 8
44 2007-10-17 00:00:00.000 5.5793 21 11
54 2007-10-17 00:00:00.000 5.2471 9 2
55 2007-10-17 00:00:00.000 5.1177 7 0
81 2007-10-17 00:00:00.000 5.5510 18 9
86 2007-10-17 00:00:00.000 5.5128 16 7
96 2007-10-17 00:00:00.000 5.5758 20 10

恩, 这个看起来还不错吧, 其实根本是没用的实际测试数据. 没人会把这些数据手工输入测试表中, 原因很简单:首先必须做一些格式化的工作. 如果需要做很多前期工作去把数据输入进测试表的话, 那么很多高手是不会花时间去回答这样的问题的. 即使把数据存文件上并用程序输入, 对一个想帮忙解决问题的人来说也是很烦的, 更别说在一个字段的DATETIME的数据类型的数据中还有个空格, 那更是让人退避三舍了.

即便是真有人回了贴并贴了代码, 除非是用了你的数据做了测试, 否则很可能那代码是错的或给的结果根本不是你想要的.


贴数据的正确方法应该是这样的

首先要问:你用什么方式贴数据才能建实际的表呢? 对!当然你应该做所有的前期工作....虽然这也会费你一些时间. 但是谁叫我们有求于人呢
这里有个方法建表和输入数据对大家(包括你自己)都容易:

写出建表代码
对, 这第一部分都是手工的....但却是值得的,不会花很多时间, 而且还会起如下的作用:
1. 很好地表示了字段的数据类型. 光这点就能回答很多不必要的提问.
2. 很好地描述了表的约束, 条件, 和主键, 也避免了你被N多回贴地"逼问", 因为你的表在实际中就是那么建的.
3. 能吸引那些能帮助你的人真正地花些时间帮你解决问题.(这点最重要)

因此, 对上面一开始给的数据, 你应该写些下面的代码:

--===== 如果该测试表已经存在, drop it
IF OBJECT_ID('TempDB..#mytable','U') IS NOT NULL
DROP TABLE #mytable

--===== 建个测试表
CREATE TABLE #mytable
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
DateValue DATETIME,
Value DECIMAL(9,4),
YearValue INT,
MonthValue INT
)

--===== 建立其他特殊要求的条件, 尤其是需要考虑时间类型时
SET DATEFORMAT DMY


注意到那个SET语句输入的原始数据是DMY(日月年)格式的. 为了避免更多的解释, SET语句被归类为"特殊条件". 这样, 那些潜水的牛人就可以在输入你的数据时根本不用考虑转换时间类型而是专心于你的问题了.


创建一些数据
当然啦, 最好的方式是用SELECT语句从实际的表中选出一些数据贴出来. 大多数人是这么做的. 不过呢, 很多人贴出了象本文一开始贴出的那种没格式化好的, 很难输入的数据. 就这一点就没人理你的贴子了, 要么人家就写些"没测试过的"代码, 要知道把你的没格式化好的数据输入到测试表中去实在太痛苦了.

其实, 你只要举手之劳就能让数据"自己输入"了.......这里有个怎样使用QUOTENAME的例子(假设表名是yourtable):

SELECT 'SELECT '
+ QUOTENAME(ID,'''')+','
+ QUOTENAME(DateValue,'''')+','
+ QUOTENAME(Value,'''')+','
+ QUOTENAME(YearValue,'''')+','
+ QUOTENAME(MonthValue,'''')
+ ' UNION ALL'
FROM yourtable


(注: 如果在生成代码时把UNION ALL去掉, 并把QUOTENAME里的单引号换成双引号, 你就能得到一个不错的CSV数据生成代码了!)

如果你在Query Analyzer(SQL2000)或Management Studio(SQL2005)的Text Mode中运行上面的代码, 就会得到个很不错的数据自动生成的输出:

SELECT '4','Oct 17 2007 12:00AM','5.1709','8','1' UNION ALL
SELECT '37','Oct 17 2007 12:00AM','5.5319','17','8' UNION ALL
SELECT '44','Oct 17 2007 12:00AM','5.5793','21','11' UNION ALL
SELECT '54','Oct 17 2007 12:00AM','5.2471','9','2' UNION ALL
SELECT '55','Oct 17 2007 12:00AM','5.1177','7','0' UNION ALL
SELECT '81','Oct 17 2007 12:00AM','5.5510','18','9' UNION ALL
SELECT '86','Oct 17 2007 12:00AM','5.5128','16','7' UNION ALL
SELECT '96','Oct 17 2007 12:00AM','5.5758','20','10' UNION ALL


删掉最后那个"UNION ALL", 加入为插入IDENTITY字段所必需的SET语句, 然后加入实际的INSERT语句. 下面就是你的代码了:

--===== All Inserts into the IDENTITY column
SET IDENTITY_INSERT #mytable ON

--===== Insert the test data into the test table
INSERT INTO #mytable
(ID, DateValue, Value, YearValue, Monthvalue)
SELECT '4','Oct 17 2007 12:00AM','5.1709','8','1' UNION ALL
SELECT '37','Oct 17 2007 12:00AM','5.5319','17','8' UNION ALL
SELECT '44','Oct 17 2007 12:00AM','5.5793','21','11' UNION ALL
SELECT '54','Oct 17 2007 12:00AM','5.2471','9','2' UNION ALL
SELECT '55','Oct 17 2007 12:00AM','5.1177','7','0' UNION ALL
SELECT '81','Oct 17 2007 12:00AM','5.5510','18','9' UNION ALL
SELECT '86','Oct 17 2007 12:00AM','5.5128','16','7' UNION ALL
SELECT '96','Oct 17 2007 12:00AM','5.5758','20','10'

--===== Set the identity insert back to normal
SET IDENTITY_INSERT #mytable OFF



一些数据类型的问题
Money和一些其他数据类型是不允许从CHAR或VARCHAR进行implicit转换的. 那么, 怎么办呢? 答案是简单的, 就是不要在数据上加引号.

在本文的例子中, 如果表的结构是象这样的话:

--===== 如果测试表已经存在, drop it
IF OBJECT_ID('TempDB..#mytable','U') IS NOT NULL
DROP TABLE #mytable

--===== 建个测试表
CREATE TABLE #mytable
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, --在实际的表中是IDENTITY字段
DateValue DATETIME,
Value MONEY,
YearValue INT,
MonthValue INT
)

--===== 建立其他特殊要求的条件, 特别是需要考虑时间类型时
SET DATEFORMAT DMY



跟着,那个"数据生成"代码应该象如下的样子 (去掉VALUE数据的引号):

SELECT 'SELECT '
+ QUOTENAME(ID,'''')+','
+ QUOTENAME(DateValue,'''')+','
+ CAST(Value AS VARCHAR)+','
+ QUOTENAME(YearValue,'''')+','
+ QUOTENAME(MonthValue,'''')
+ ' UNION ALL'
FROM yourtable


这样的话就生成能插入character-resistant的MONEY数据类型了:

SELECT '4','Oct 17 2007 12:00AM',5.1709,'8','1' UNION ALL
SELECT '37','Oct 17 2007 12:00AM',5.5319,'17','8' UNION ALL
SELECT '44','Oct 17 2007 12:00AM',5.5793,'21','11' UNION ALL
SELECT '54','Oct 17 2007 12:00AM',5.2471,'9','2' UNION ALL
SELECT '55','Oct 17 2007 12:00AM',5.1177,'7','0' UNION ALL
SELECT '81','Oct 17 2007 12:00AM',5.5510,'18','9' UNION ALL
SELECT '86','Oct 17 2007 12:00AM',5.5128,'16','7' UNION ALL
SELECT '96','Oct 17 2007 12:00AM',5.5758,'20','10'



最后....
如果你做了上述的工作, 那么你很重要的求助贴中的数据和代码应该象:

--===== 如果测试表已经存在, drop it
IF OBJECT_ID('TempDB..#mytable','U') IS NOT NULL
DROP TABLE #mytable

--===== 建个测试表
CREATE TABLE #mytable
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, --在实际的表中是IDENTITY字段
DateValue DATETIME,
Value MONEY,
YearValue INT,
MonthValue INT
)

--===== 建立其他特殊要求的条件, 特别是需要考虑时间类型时
SET DATEFORMAT DMY

--===== All Inserts into the IDENTITY column
SET IDENTITY_INSERT #mytable ON

--===== Insert the test data into the test table
INSERT INTO #mytable
(ID, DateValue, Value, YearValue, Monthvalue)
SELECT '4','Oct 17 2007 12:00AM',5.1709,'8','1' UNION ALL
SELECT '37','Oct 17 2007 12:00AM',5.5319,'17','8' UNION ALL
SELECT '44','Oct 17 2007 12:00AM',5.5793,'21','11' UNION ALL
SELECT '54','Oct 17 2007 12:00AM',5.2471,'9','2' UNION ALL
SELECT '55','Oct 17 2007 12:00AM',5.1177,'7','0' UNION ALL
SELECT '81','Oct 17 2007 12:00AM',5.5510,'18','9' UNION ALL
SELECT '86','Oct 17 2007 12:00AM',5.5128,'16','7' UNION ALL
SELECT '96','Oct 17 2007 12:00AM',5.5758,'20','10'

--===== Set the identity insert back to normal
SET IDENTITY_INSERT #mytable OFF



...全文
464 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
顶。不过貌似看的不是太懂
tianhuo_soft 2008-11-22
  • 打赏
  • 举报
回复
up
rockyvan 2008-08-05
  • 打赏
  • 举报
回复
好是好!但是有很多人是新手,根本不知道該怎麽寫這些東西!
建議版主將此帖推薦或置頂,讓不知道的人可以學習學習!
胡矣 2008-08-05
  • 打赏
  • 举报
回复
JF
happysophie 2008-07-16
  • 打赏
  • 举报
回复
说得好。
其实论坛中的好心人非常多,大家都是建表,输入数据,很麻烦。
都能做到你说的那样该多好!
hery2002 2008-07-03
  • 打赏
  • 举报
回复
up
bwu851 2008-07-03
  • 打赏
  • 举报
回复
Sorry, 因为字数忒多, 不让我发一篇. 我有不想删节, 左思右想了一会儿, 决定发成两部分了.
lff642 2008-07-03
  • 打赏
  • 举报
回复
学习.看看.
bwu851 2008-07-03
  • 打赏
  • 举报
回复
在论坛上怎么贴数据和脚本才能得到最好(最快)的帮助 (part two)
Tips:

因为不想代人写作业或帮人回答在线的"面试问题", 很多时候, 大多象我这样的人会先让你把你试过的代码贴出来. 当然, 如果我们没法"读"你的代码,就像后面举例的这段糟糕的代码,我们根本不会看你的绝望求助贴第二眼:

select v.* from #mytable v, ( select min(id) as firstidofstagnation from #mytable v, ( select min(id) as lastidbeforestagnation from ( select top 2 value, max(id) as id from #mytable group by value order by max(id) desc )x )ls where v.id > ls.lastidbeforestagnation )fs where v.id = fs.firstidofstagnation


每次我看到这样的垃圾代码时, 反应就是: "如果你自己都不在乎自己的代码, 那我凭什么在乎?" 然后, 我就跳过去下一个贴子了. 也就是说,你不规范自己的代码的话, 谁会在这种垃圾代码上浪费时间?

还有一点, 注释很有帮助....你的代码越容易读, 许多象我一样的有心帮助的人就更可能来帮你. 因此, 如果上面那段代码改成下面的样子的话, 就可能很快吸引眼球的: (完全一样的代码, 只是更规范, 并加了一些注释)

SELECT v.*
FROM #MyTable v,
(--==== Derived table "fs" finds ID of the first row
-- where stanation of VALUE occurs
SELECT MIN(ID) AS FirstIDOfStagnation
FROM #MyTable v,
(--==== Derived table "ls" finds last ID before
--stagnation of VALUE
SELECT MIN(ID) AS LastIDBeforeStagnation
FROM (--==== Derived table "x" finds the ID's of the
-- last value and the value before that
SELECT TOP 2
Value, MAX(ID) AS ID
FROM #MyTable
GROUP BY Value
ORDER BY MAX(ID) DESC
)x
)ls
WHERE v.ID > ls.LastIDBeforeStagnation
)fs
WHERE v.ID = fs.FirstIDOfStagnation



结论
给你自己一个很好的机会为你的很重要的问题得到既快又正确的回答, 而不是象本文开头的例子那样贴出个几近无用的数据。
使想给你帮助的人根本不用去考虑怎么输入你的数据, 或使你的代码更容易读, 这样的话就表示你的问题很重要。记住, 如果你不在乎你的数据或代码看起来怎么样, 那我更不在乎, 甚至我可能都不会再看你的贴子。Help us help you.

********************************** 完 **************************************

(译者注: 在这里加段话哈. 我发现坛子里很多朋友是很不错的, 即使很多提问的人都犯了上面说的错, 但他(她)们还是积极地自己建表, 并输入数据去帮着测试. 很让我佩服. 我是做不到的. 我最多是给个代码. 我觉得连像我这样的低手看到不规范的贴子都烦, 更何况其他高手呢?

还是最后那句是最重要的: Help us help you. )

11,849

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 非技术版
社区管理员
  • 非技术版社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧