<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>guzik &#187; OTC Terminal</title>
	<atom:link href="http://guzik.net.pl/blog/tag/otc-terminal/feed/" rel="self" type="application/rss+xml" />
	<link>http://guzik.net.pl/blog</link>
	<description>Mój blog</description>
	<lastBuildDate>Fri, 10 Feb 2012 23:44:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>MySQL: konwersja daty i import plików &#8211; studium przypadku</title>
		<link>http://guzik.net.pl/blog/2010/01/mysql-konwersja-daty-i-import-plikow-studium-przypadku/</link>
		<comments>http://guzik.net.pl/blog/2010/01/mysql-konwersja-daty-i-import-plikow-studium-przypadku/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 14:07:28 +0000</pubDate>
		<dc:creator>guzik</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[OTC]]></category>
		<category><![CDATA[OTC Terminal]]></category>

		<guid isPermaLink="false">http://guzik.net.pl/blog/?p=1495</guid>
		<description><![CDATA[Niniejszy wpis powstał przy rozwiązywaniu konkretnego problemu. Jest tu opis polecenia LOAD DATA INFILE (import danych z pliku) oraz sposób wykonania konwersji daty podczas importu danych, co może komuś się przydać (niekoniecznie przy walce z takim samym problemem). Opis problemu: Potrzebujemy wyciągnąć wszystkie próby logowania z wykorzystaniem programu OTC Terminal konkretnego dnia, albo o konkretnej [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" title="MySQL logo" src="http://www.mysql.com/common/logos/sakila.png" alt="" width="121" height="79" />Niniejszy wpis powstał przy rozwiązywaniu konkretnego problemu. Jest tu opis polecenia <a title="http://dev.mysql.com/doc/refman/5.1/en/load-data.html" href="http://dev.mysql.com/doc/refman/5.1/en/load-data.html">LOAD DATA INFILE</a> (import danych z pliku) oraz sposób wykonania konwersji daty podczas importu danych, co może komuś się przydać (niekoniecznie przy walce z takim samym problemem).<br />
<span id="more-1495"></span><br />
<strong>Opis problemu</strong>: Potrzebujemy wyciągnąć wszystkie próby logowania z wykorzystaniem programu <a title="http://www.otc.pl/index.asp?s=84&amp;l=1" href="http://www.otc.pl/index.asp?s=84&amp;l=1">OTC Terminal</a> konkretnego dnia, albo o konkretnej godzinie każdego dnia zdefiniowanego użytkownika.</p>
<p><strong>Rozeznanie terenu</strong>: Wspomniany program tworzy log w następującym formacie:</p>
<blockquote><p><code> 4. BS2          LOGIN ERROR   25.03.2009 07:02:08  Password expired.<br />
4. BS2          CHPWD OK      25.03.2009 07:02:16  Password for user 'BS2' successfully changed.<br />
0. BS2          LOGIN OK      30.03.2009 06:54:25<br />
1. BS2          LOGIN OK      30.03.2009 06:54:29<br />
0. BS2          LOGOUT OK     30.03.2009 06:54:29<br />
1. BS2          LOGOUT OK     30.03.2009 06:54:42<br />
10. BS2          LOGOUT ERROR  24.04.2009 11:47:58  Login limit (session)<br />
6. BS2          LOGIN ERROR   21.05.2009 14:32:57  No such name<br />
</code></p></blockquote>
<p>Nie wnikam co oznacza pierwsza kolumna w logach, kolejne to: nazwa użytkownika, akcja, data oraz godzina, a także dodatkowa informacja dla akcji. Nie interesuje nas zarówno pierwsza, jak i ostatnia kolumna. Plik tekstowy ma kolumny o stałej szerokości (tutaj tego nie widać).<br />
Do realizacji zadania można użyć <a title="http://www.gnu.org/software/gawk/" href="http://www.gnu.org/software/gawk/">awk</a>, <a title="http://sed.sourceforge.net/" href="http://sed.sourceforge.net/">sed</a>, <a title="http://www.gnu.org/software/grep/" href="http://www.gnu.org/software/grep/">grep</a>, <a title="http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/find.mspx?mfr=true" href="http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/find.mspx?mfr=true">find</a> (Windows) lub innych podobnych narzędzi w połączeniu z wyrażeniami regularnymi, ale można też skorzystać z bazy danych, która będzie przechowywać wspomniane informacje w konkretnym formacie, a samo przeszukiwanie będzie wygodniejsze, szybsze i bardziej elastyczne.</p>
<p><strong>Realizacja</strong>: Za pomocą arkusza kalkulacyjnego przekształciłem logi w format CSV (najszybsze, co przyszło mi do głowy). Wyrzuciłem niepotrzebne kolumny. Utworzyłem tabelę w MySQL, która może wciągnąć te dane:</p>
<blockquote><p><code>CREATE TABLE `trmlog` (<br />
`user` char(3) NOT NULL,<br />
`action` varchar(24) DEFAULT NULL,<br />
`date` date DEFAULT NULL,<br />
`time` time DEFAULT NULL,<br />
KEY `useridx` (`user`),<br />
KEY `dateidx` (`date`)<br />
) ENGINE=InnoDB DEFAULT CHARSET=utf8</code></p></blockquote>
<p>Data i godzina są osobno. Jako, że data ma postać DD.MM.YYYY, a chcemy YYYY-MM-DD, stworzyłem funkcję, która może to skonwertować (nie wiem czy MySQL w locie coś może sam zrobić):</p>
<blockquote><p><code>delimiter //</code></p>
<p><code><a title="http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html" href="http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html">CREATE FUNCTION</a> dateconv (date CHAR(10)) RETURNS DATE<br />
BEGIN<br />
RETURN CONCAT(<a title="http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_substring" href="http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_substring">SUBSTRING</a>(date, 7), "-", SUBSTRING(date, 4, 2), "-", SUBSTRING(date, 1, 2));<br />
END//</code></p>
<p><code>delimiter ;</code></p></blockquote>
<p>I ostatecznie zaimportowałem dane:</p>
<blockquote><p><code>LOAD DATA INFILE 'E:\\temp\\termlog\\log.csv' INTO TABLE trmlog FIELDS TERMINATED BY ';' (user, action, @var1, time) SET date = dateconv(@var1);</code></p></blockquote>
<p>Uwagi wymaga proces konwersji kolumny z datą. Domyślnie LOAD DATA INFILE zakłada, że każde pole w pliku CSV odpowiada jednej kolumnie w tabeli. Jeśli chcemy zaimportować dane tylko do niektórych kolumn, musimy podać ich nazwy (czy sam ich porządek). Jeśli natomiast chcemy je w jakiś sposób przekształcić, używamy klauzuli <code>SET</code>, która może przybrać różne formy. Po przykłady odsyłam do <a title="http://dev.mysql.com/doc/refman/5.1/en/" href="http://dev.mysql.com/doc/refman/5.1/en/">dokumentacji MySQL</a>. U mnie wygląda to tak, że do kolumny <code>date</code> wciągamy dane, które wyrzuci nam (nasza własna) funkcja <code>dateconv()</code>. Może nie do końca intuicyjne, ale nie tak trudne.<br />
Dalej obrabiamy to jak chcemy w SQL.</p>
<p>Oczywiście nie musimy używać MySQL, a jeśli już użyliśmy, zawsze możemy migrować do innej bazy:</p>
<li><a title="http://www.heise-online.pl/newsticker/news/item/Microsoft-chce-pomoc-w-migracji-z-MySQL-a-na-SQL-Server-902665.html" href="http://www.heise-online.pl/newsticker/news/item/Microsoft-chce-pomoc-w-migracji-z-MySQL-a-na-SQL-Server-902665.html">Microsoft chce pomóc w migracji z MySQL-a na SQL Server</a></li>
]]></content:encoded>
			<wfw:commentRss>http://guzik.net.pl/blog/2010/01/mysql-konwersja-daty-i-import-plikow-studium-przypadku/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

