F # генерировать SQL из CSV - PullRequest
       15

F # генерировать SQL из CSV

2 голосов
/ 17 декабря 2009

Я недавно изучал F # и функциональное программирование. Одно приложение, которое я нашел очень полезным, - это генерирование вставок SQL для загрузки данных из CSV (или таблицы Excel) с некоторыми связанными идентификаторами.

Следующий код - мой результат, который, я думаю, очень пригодится в будущем. Я думал, что другие могли бы также извлечь выгоду из этого, и я приветствую предложения и другие сценарии, которые люди нашли бесценными в своей коллекции:

// Returns some dataload SQL for area mapping.
open System
open System.IO

// Read and split CSV into lists
let map_ngo_area = File.ReadAllLines(@"P:\MY_TABLE.csv") 
                        |> Array.to_list
                        |> List.map(fun x -> (x.Split([|','|]) 
                                                |> Array.map(fun y -> y.Trim())) 
                                                |> Array.to_list)

// Output Formatting function
let format_sql_record = "INSERT INTO MyTable
     (ID, REF1_ID, REF2_ID, CreatedUser, CreatedDateTime, LastModifiedUser, LastModifiedDateTime)
     VALUES
     ( {0}, {1}, {2}, 'system', getDate(), 'system', getDate() )"

 // Generate the SQL for the given list.  
let generate_sql list = list |> List.mapi(fun index row -> 
                                            match row with
                                                | [ngo_id; area_id] -> String.Format(format_sql_record, ((int index)+1), ngo_id, area_id) |> printfn "%s"
                                                | _ -> printfn "")

// Main Execution
map_ngo_area |> generate_sql |> ignore

// End of program, pause to view console output.
System.Console.ReadKey() |> ignore

Есть предложения по улучшению моего кода F # или процесса? Комментарии также приветствуются, так как я довольно новичок в этой парадигме, и меняющееся мышление не так ожидаемо, как я ожидал.

Спасибо:)

Ответы [ 2 ]

6 голосов
/ 17 декабря 2009

Вот несколько предложений:

  • Не используйте List.mapi с функциями, которые возвращают unit, так как вы не можете ничего сделать с полученным unit list. Вместо этого вы должны использовать List.iteri, что позволит вам пропустить |> ignore в конце вашего основного раздела исполнения.
  • Если пойти дальше, вместо того, чтобы generate_sql печатать сгенерированные строки по одной, лучше создать список строк. Обратите внимание, что в этом случае вы вернетесь к использованию List.mapi, поскольку применяемая функция будет возвращать результат для каждой строки.
  • Используйте форматирование печати F # вместо String.Format. Например, вместо format_sql_record быть строкой, иметь функцию типа int->string->string->string: let format_sql_record = sprintf "INSERT INTO ... VALUES (%i, %s, %s, ...)"
  • В зависимости от используемой версии F # вам, вероятно, следует использовать переименованную функцию Array.toList вместо Array.to_list, поскольку это имя будет использоваться в окончательном выпуске F #.
4 голосов
/ 17 декабря 2009

Вы также можете использовать сопоставление с образцом для массивов:

let map_ngo_area = File.ReadAllLines(@"P:\MY_TABLE.csv") 
                    |> Array.to_list
                    |> List.map(fun x -> (x.Split([|','|]) 
                                            |> Array.map(fun y -> y.Trim())) 

let generate_sql list = list |> List.mapi(fun index row -> 
                                            match row with
                                            | [| ngo_id; area_id |] -> printfn ...
                                            | _ -> printfn "")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...