使用F#创建插入语句

时间:2012-07-26 20:03:10

标签: database f#

我每隔几个月左右使用一次F#,在它之间我似乎忘了一切,所以我希望你能原谅我的无知。我的下面的代码是从雅虎提取数据。这是一个很好的例子,代表了我需要做的事情。返回的第一行具有列标题。我需要获取数据(列表的尾部)并将其插入数据库。基于返回的列标题生成插入语句的最佳方法是什么(列标题与数据库列名称匹配)?

在下面的例子中dataWithHeaders。[0]将包含“日期,开盘价,最高价,最低价,收盘价,成交量,调整收盘价”。我应该只拿这个字符串并在标题周围放置括号来创建插入吗?然后在insertData中添加值作为参数?有更优雅的解决方案吗?

let url = System.String.Format("http://ichart.finance.yahoo.com/table.csv?s={0}&g=d&ignore=.csv", "FB")

let splitLineIntoArray (line : string) = 
    line.Split(",".ToCharArray())

let insertData (data : string[]) =
    // insert data
    ()

let client = new WebClient()
let dataWithHeaders = 
    client.DownloadString(url).Split(Environment.NewLine.ToCharArray())

let data =
    dataWithHeaders
    |> Array.toList
    |> List.tail
    |> List.map(splitLineIntoArray)
    |> List.iter insertData

2 个答案:

答案 0 :(得分:8)

如果要将数据加载到SQL Server,可以使用this excellent CSV reader(免费)和SqlBulkCopy类。它简单而有效。

let loadStockPrices ticker =
  use client = new WebClient()
  let url = sprintf "http://ichart.finance.yahoo.com/table.csv?s=%s&g=d&ignore=.csv" ticker
  use stringReader = new StringReader(client.DownloadString(url))
  use csvReader = new CsvReader(stringReader, hasHeaders=true)
  use con = new SqlConnection("<connection_string>")
  con.Open()
  use bulkCopy = new SqlBulkCopy(con, DestinationTableName="<destination_table>")
  bulkCopy.WriteToServer(csvReader)

目标表应与传入数据(OHLC等)具有相同的列。

答案 1 :(得分:4)

编辑:类型提供程序可能是一个很好的方法,但SqlBulkCopy是def。以其简洁而着称。

为插入输入提供商代码:http://msdn.microsoft.com/en-us/library/hh361033(v=vs.110).aspx#BKMK_UpdateDB

type dbSchema = SqlDataConnection<"Data Source=MYSERVER\INSTANCE;Initial Catalog=MyDatabase;Integrated Security=SSPI;">
let db = dbSchema.GetDataContext()

// Enable the logging of database activity to the console.
db.DataContext.Log <- System.Console.Out

let newRecord = new dbSchema.ServiceTypes.Table1(Id = 100,
                                                 TestData1 = 35, 
                                                 TestData2 = 2.0,
                                                 Name = "Testing123")
let newValues =
    [ for i in [1 .. 10] ->
          new dbSchema.ServiceTypes.Table3(Id = 700 + i,
                                           Name = "Testing" + i.ToString(),
                                           Data = i) ]
// Insert the new data into the database.
db.Table1.InsertOnSubmit(newRecord)
db.Table3.InsertAllOnSubmit(newValues)
try
    db.DataContext.SubmitChanges()
    printfn "Successfully inserted new rows."
with
   | exn -> printfn "Exception:\n%s" exn.Message

我做了类似的事情。实际上,我在观看Luca Bolognese时写的这段代码就F#进行了演示。这实际上将刮掉雅虎的饲料并返回标准开发。和股价的差异。

此处的完整项目:https://github.com/djohnsonm/Stock-Ticker-App

open System.Net
open System.IO

let internal loadPrices ticker = async {
let url = @"http://ichart.finance.yahoo.com/table.csv?s=" + ticker + "&d=6&e=22&f=2011&g=d&a=2&b=13&c=1986&ignore=.csv"
let req = WebRequest.Create(url)
let resp = req.GetResponse()
let stream = resp.GetResponseStream()
let reader = new StreamReader(stream)
let csv = reader.ReadToEnd()
let prices = 
    csv.Split([|'\n'|])
    |> Seq.skip 1
    |> Seq.map (fun line -> line.Split([|','|]))
    |> Seq.filter(fun values -> values |> Seq.length = 7)
    |> Seq.map(fun values ->
        System.DateTime.Parse(values.[0]),
        float values.[6])
return prices}

type StockAnalyzer (lprices, days) =
    let prices =
        lprices
        |> Seq.map snd
        |> Seq.take days
    static member GetAnalyzers (tickers, days) =
        tickers
        |> Seq.map loadPrices
        |> Async.Parallel
        |> Async.RunSynchronously
        |> Seq.map (fun prices -> new StockAnalyzer(prices, days))
    member s.Return =
        let lastPrice = prices |> Seq.nth 0
        let startPrice = prices |> Seq.nth(days-1)
        lastPrice / startPrice - 1.
    member s.StdDev =
        let logRets =
            prices
            |> Seq.pairwise
            |> Seq.map (fun (x,y) -> log(x/y))
        let mean = logRets |> Seq.average
        let sqr x = x * x
        let var = logRets |> Seq.averageBy (fun r -> sqr (r-mean))
        sqrt var