CSDN的朋友,从明天本人开始要为生计奔波,没时间上CSDN了,混迹CSDN一个月,有什么得罪的地方,请多多包涵。消失之前,总想写点什么,纯技术帖是写不出来,太久没玩数据库,前几天看到有朋友问道股票数据的问题,那就写一个直接用OPENROWSET读取同花顺股票数据的方法吧,适合盘后分析。方法不算好方法,但比较简单,以前我做数据分析的时候,都是用这个方法,平时数据库不存数据,需要分析的时候动态调入,调入速度很快,有更好方法的朋友请多多指教。下面是日线数据(600787只是例子不构成任何投资建议):
--===============================================================
-- 文件头16个字节剖析(日线)
-- 0x6864312E3000 6  固定
-- 0x????????     4  记录数
-- 0x4800         2  记录开始位置: 64是错的, 文件头 + 列定义 = 72
-- 0x3800         2  每记录的长度: 56
-- 0x0E00         2  每记录的列数: 14
-----------------------------------------------------------------
-- 列定义: 04表示列长度
-- 0x01300004     4 日期
-- 0x07700004     4 开盘价
-- 0x08700004     4 最高价
-- 0x09700004     4 最低价
-- 0x0B700004     4 收盘价
-- 0x13700004     4 成交金额(元)
-- 0x0D700004     4 成交量(股)
-- 0x0E700004     4 FFFFFFFF
-- 0x0F700004     4 FFFFFFFF
-- 0x11700004     4 FFFFFFFF
-- 0x12700004     4 FFFFFFFF
-- 0x50700004     4 FFFFFFFF
-- 0xE7700004     4 FFFFFFFF
-- 0xE8700004     4 FFFFFFFF
--===============================================================
if object_id('tempdb.dbo.#') is not null drop table #
go
declare @ varbinary(max), @max int, @e float
select @ = BulkColumn, @e = 10 from OPENROWSET(BULK N'X:\...\history\shase\day\600787.day', SINGLE_BLOB) as bin
select @max = substring(@,10,1)+substring(@,9,1)+substring(@,8,1)+substring(@,7,1)
select top (@max) n = identity(int,72,56) into # from syscolumns a, syscolumns b
;with cte as
(
select
-- SQL没有提供按字节reverse(binary)的函数或方法,只能substring每个字节倒过来合成:
d = convert(int,substring(@, 4+n,1)+substring(@, 3+n,1)+substring(@, 2+n,1)+substring(@, 1+n,1)),
o = convert(int,substring(@, 8+n,1)+substring(@, 7+n,1)+substring(@, 6+n,1)+substring(@, 5+n,1))&0x0FFFFFFF,
p = convert(int,substring(@,12+n,1)+substring(@,11+n,1)+substring(@,10+n,1)+substring(@, 9+n,1))&0x0FFFFFFF,
q = convert(int,substring(@,16+n,1)+substring(@,15+n,1)+substring(@,14+n,1)+substring(@,13+n,1))&0x0FFFFFFF,
r = convert(int,substring(@,20+n,1)+substring(@,19+n,1)+substring(@,18+n,1)+substring(@,17+n,1))&0x0FFFFFFF,
s = convert(int,substring(@,24+n,1)+substring(@,23+n,1)+substring(@,22+n,1)+substring(@,21+n,1))&0x0FFFFFFF,
t = convert(int,substring(@,28+n,1)+substring(@,27+n,1)+substring(@,26+n,1)+substring(@,25+n,1))&0x0FFFFFFF,
u = convert(int,substring(@, 8+n,1))/16,
v = convert(int,substring(@,12+n,1))/16,
w = convert(int,substring(@,16+n,1))/16,
x = convert(int,substring(@,20+n,1))/16,
y = convert(int,substring(@,24+n,1))/16,
z = convert(int,substring(@,28+n,1))/16
from #
)
select
id = row_number()over(order by d desc),
日期 = d,
开盘 = o*power(@e,(u&7)*power(-1,sign(u&8))),
最高 = p*power(@e,(v&7)*power(-1,sign(v&8))),
最低 = q*power(@e,(w&7)*power(-1,sign(w&8))),
收盘 = r*power(@e,(x&7)*power(-1,sign(x&8))),
金额 = s*power(@e,(y&7)*power(-1,sign(y&8))),
成交 = t*power(@e,(z&7)*power(-1,sign(z&8)))
from cte/*
id       日期        开盘     最高     最低     收盘     金额         成交
-------- ----------- -------- -------- -------- -------- ------------ ------------
1        20100820    8.35     8.39     8.09     8.25     107211287    13054826
2        20100819    8.61     8.61     8.38     8.45     86104465     10147807
3        20100818    8.38     8.65     8.32     8.61     115737744    13614804
.        .           .        .        .        .        .            .
.        .           .        .        .        .        .            .
.        .           .        .        .        .        .            .
3214     19970122    10.75    10.8     10.23    10.46    29105000     2810400
3215     19970121    10.8     11.42    10.8     10.93    94426000     8567400
*/下面是分钟线数据,具体内容就不写了,只是调整一下数字表#标识列的初始大小和增量问题:
--===============================================================
-- 文件头16个字节剖析(5/1分钟线)
-- 0x6864312E3000 6  固定
-- 0x????????     4  记录数
-- 0x3800         2  记录开始位置: 56是对的, 文件头 + 列定义 = 56
-- 0x2800         2  每记录的长度: 40
-- 0x0A00         2  每记录的列数: 10
-----------------------------------------------------------------
-- 列定义: 04表示列长度
-- 0x01300004     4 日期: 已加密, 不要问怎么解密, 我不知道.
-- 0x07700004     4 开盘价
-- 0x08700004     4 最高价
-- 0x09700004     4 最低价
-- 0x0B700004     4 收盘价
-- 0x13700004     4 成交金额(元)
-- 0x0D700004     4 成交量(股)
-- 0x0E700004     4 FFFFFFFF
-- 0x0F700004     4 FFFFFFFF
-- 0x12700004     4 FFFFFFFF
--===============================================================
用SQL来分析二进制文件格式还是比较方便的,可以直接select/convert,快捷直观。我一般用来分析game的存档文件,呵呵。欢迎排砖。

解决方案 »

  1.   

    j接分,再仔细看看着这2段SQL
      

  2.   

    我感兴趣的是用SQL直接读取网络上的数据。不写扩展存储过程。期待你用sp_OA。。写一份我好照抄源代码,哈哈
      

  3.   

    请教楼主,我在SQL Server2000的查询分析器里复制楼主的代码,直接执行提示如下错误:服务器: 消息 170,级别 15,状态 1,行 1
    第 1 行: 'max' 附近有语法错误。
    服务器: 消息 137,级别 15,状态 1,行 2
    必须声明变量 '@'。
    服务器: 消息 137,级别 15,状态 1,行 3
    必须声明变量 '@'。
    服务器: 消息 137,级别 15,状态 1,行 9
    必须声明变量 '@'。
    服务器: 消息 195,级别 15,状态 1,行 25
    'row_number' 不是可以识别的 函数名。
    我对SQL不太清楚,望指教,谢谢!
      

  4.   


    #1是2005的方法,2000的方法如下:--==============================================================
    -- SQL Server 2000 直接读取同花顺股票数据
    --==============================================================----------------------------------------------------------------
    -- 以下内容参考 http://topic.csdn.net/t/20041009/17/3438209.html
    -- textcopy.exe 可以在 SQL Server 2000 安装光盘或安装目录找到
    -- 将 textcopy.exe 文件复制到系统目录或设置环境变量
    ----------------------------------------------------------------
    if object_id('Test') is not null drop table Test
    go
    create table Test (id int, b image)
    go
    insert Test select 1, 0x
    go
    exec sp_textcopy
    'servername',
    'sa',
    'password',
    'databasename',
    'Test',
    'b',
    'X:\...\history\shase\day\600787.day',
    'where id=1',
    'I'
    go
    ----------------------------------------------------------------if object_id('tempdb.dbo.##') is not null drop table ##
    godeclare @max int, @e float
    select @max = convert(int,substring(b,10,1)+substring(b,9,1)+substring(b,8,1)+substring(b,7,1)), @e = 10 from Test where id = 1
    exec ('select top '+@max+' n = identity(int,72,56) into ## from syscolumns a, syscolumns b')select
    日期 = d,
    开盘 = o*power(@e,(u&7)*power(-1,sign(u&8))),
    最高 = p*power(@e,(v&7)*power(-1,sign(v&8))),
    最低 = q*power(@e,(w&7)*power(-1,sign(w&8))),
    收盘 = r*power(@e,(x&7)*power(-1,sign(x&8))),
    金额 = s*power(@e,(y&7)*power(-1,sign(y&8))),
    成交 = t*power(@e,(z&7)*power(-1,sign(z&8)))
    from
    (
    select
    d = convert(int,substring(b, 4+n,1)+substring(b, 3+n,1)+substring(b, 2+n,1)+substring(b, 1+n,1)),
    o = convert(int,substring(b, 8+n,1)+substring(b, 7+n,1)+substring(b, 6+n,1)+substring(b, 5+n,1))&0x0FFFFFFF,
    p = convert(int,substring(b,12+n,1)+substring(b,11+n,1)+substring(b,10+n,1)+substring(b, 9+n,1))&0x0FFFFFFF,
    q = convert(int,substring(b,16+n,1)+substring(b,15+n,1)+substring(b,14+n,1)+substring(b,13+n,1))&0x0FFFFFFF,
    r = convert(int,substring(b,20+n,1)+substring(b,19+n,1)+substring(b,18+n,1)+substring(b,17+n,1))&0x0FFFFFFF,
    s = convert(int,substring(b,24+n,1)+substring(b,23+n,1)+substring(b,22+n,1)+substring(b,21+n,1))&0x0FFFFFFF,
    t = convert(int,substring(b,28+n,1)+substring(b,27+n,1)+substring(b,26+n,1)+substring(b,25+n,1))&0x0FFFFFFF,
    u = convert(int,substring(b, 8+n,1))/16,
    v = convert(int,substring(b,12+n,1))/16,
    w = convert(int,substring(b,16+n,1))/16,
    x = convert(int,substring(b,20+n,1))/16,
    y = convert(int,substring(b,24+n,1))/16,
    z = convert(int,substring(b,28+n,1))/16
    from ##, Test where Test.id = 1
    ) t
    order by 1 desc