poniedziałek, 23 marca 2009

Zmiana compatibility level

Dziś na stronie wss.pl znalazłem taki oto skrypt
Służy on do sprawdzenia kompatybilności obiektów w bazie danych podczas zmiany compatibility level na wyższy (np. z 2000 do 2005).

if OBJECT_ID('tempdb..#t') is not null
drop table #t

create table #t
(
name sysname not null primary key
, [type] char(2) not null
, error bit not null default 0
, done bit not null default 0
)

insert into #t (name, [type], error, done)
select name, [type], 0, 0 from sys.objects WHERE TYPE IN ('P', 'FN', 'IF', 'TF', 'V') order by name

declare @name sysname
declare @type char(2)

declare @i int
set @i = 0

while exists (select * from #t where done = 0)
begin
set @i = @i + 1
select top 1
@type = type
, @name = name
from #t
where done = 0

BEGIN TRY
IF @type = 'V'
exec sp_refreshview @name
ELSE
exec sp_refreshsqlmodule @name
END TRY
BEGIN CATCH
if XACT_STATE() = -1 rollback tran
update #t set error = 1 where name = @name
END CATCH

update #t set done = 1 where name = @name
print ltrim(str(@i)) + ' - ' + @name

if @i > (select count(*) from #t)
break
end

Udawanie Rank w MySQL

Dziś po chwili szperania w internecie udało mi się zbudować zapytanie w MySQL-u posiadające ciekawą konstrukcję podobną do RANK z MSSQL-a. umożliwiła mi ona zliczenie elementów w bieżącym zapytaniu w sposób sekwencyjny. Oto kod SQL:

select * from (

SELECT
r2.`id`,
r2.`photo_id`,
case
when
case when r2.`photo_id` <> @grupa then 1
else 0 end = 1 then @rownum:= 0
else @rownum:= @rownum
end as tr,
@rownum:= @rownum+ 1 AS rank,
@grupa := r2.`photo_id` as gr
FROM
`photos_comments` r2, (SELECT @rownum := 0, @grupa := '', @grupa ) r
GROUP BY
r2.`photo_id`,
rank
) as tab_rank, `photos`

where (tab_rank.rank <=5) and (`photos`.`id` = tab_rank.`photo_id`)

Na stronie http://forums.devshed.com/mysql-help-4/mysql-rank-function-487657.html znalazłem coś takiego:


SET @rank = 1, @prev_val = NULL, @prev_rank = NULL;
SELECT rank FROM
(
SELECT @rank := IF(@prev_val!=uXP,@prev_rank+1,@rank) AS rank
, @prev_val := uXP AS uXP
, @prev_rank := @rank AS prevRank
, t.uID
, t.uName
FROM
(
SELECT uID, uName, SUM(tblbase.basXP) AS uXP
FROM tbluser INNER JOIN tblbase ON tbluser.uID = tblbase.basUserID
GROUP BY tblbase.basUserID
ORDER BY uXP DESC
) AS t
) AS showRank WHERE uID = 5

To chyba esencja tego czym można określić miano Rank dla MySQL

czwartek, 19 marca 2009

Prosta funkcja sprawdzająca stan serwera

Wykorzystałem tutaj właściwość State obiektu ADODB.Connection
Funkcja posiada 2 parametry:
sConn - jest to connectionstring
Timeout - określa maksymalny czas sprawdzania



Function ServerTest(sConn As String, Optional Timeout As Long = 5) As Boolean

On Error GoTo ERR_Handler:
Dim aConn As ADODB.Connection

Set aConn = New ADODB.Connection

aConn.ConnectionTimeout = Timeout
aConn.ConnectionString = sConn
aConn.Open

ServerTest = CBool(aConn.State)

aConn.Close
END_Handler:

Set aConn = Nothing

Exit Function

ERR_Handler:

ServerTest = False

Resume END_Handler:

End Function

niedziela, 15 marca 2009

Klasa Logująca w VBA

Dziś w zasadzie przypadkiem poprawiłem kawałek kodu, można powiedzieć klasę do logowania czegokolwiek w plikach tekstowych. W zasadzie całość prosta jak drut :) a co najważniejsze działa.

Jedyną kwestią techniczną na jaką trzeba zwrócić uwagę to nazwa klasy w projekcie ja dałem: cLog
'*************** class cLog start *************************
Option Explicit

Dim sFileName As String
Dim sFile As String
Dim sPath As String
Dim sISAMTable As String
Dim sDelimiter As String

Public Event Error(oErr As ErrObject)

Public Property Let Delimiter(sTmp As String)
    If Len(sTmp) > 1 Then
        Err.Raise vbObjectError + 501, "cLog.Delimiter", "Delimiter o niepoprawnej długości"
        Exit Property
    End If
    sDelimiter = sTmp
End Property

Public Property Get Delimiter() As String
    Delimiter = sDelimiter
End Property

Public Property Let File(sTmp As String)
    If Len(sTmp) < 3 And InStr(sTmp, ".") = 0 Then
        Err.Raise vbObjectError + 502, "cLog.File", "Niepoprawna nazwa pliku"
        Exit Property
    End If
    sFileName = sTmp
End Property

Public Property Get File() As String
    File = sFileName
End Property

Private Sub Class_Initialize()

    sPath = CurrentProject.Path
    sFile = "log" & Format(Now, "yyyymmdd") & ".txt"
    sFileName = Join(Array(sPath, sFile), "\")

    sDelimiter = ";"

End Sub

Public Sub Log(procedura As String, akcja As String, inne As String)

    On Error GoTo ERR_Handler:

    Dim File As Long

    File = FreeFile()

    If Dir(sFileName) = "" Then
        Open sFileName For Output As #File
        Print #File, "godzina" & sDelimiter & "procedura" & sDelimiter & "akcja" & sDelimiter & "inne"
    Else
        Open sFileName For Append As #File
    End If
    Print #File, Format(Now(), "yyyy-mm-dd hh:Nn:ss") & sDelimiter & procedura & sDelimiter & akcja & sDelimiter & inne
    
END_Handler:
    
    Close #1    ' Close file.
    Exit Sub

ERR_Handler:

    RaiseEvent Error(Err)
    Resume END_Handler:

End Sub

Public Sub Kill(Optional sFile)

    On Error GoTo ERR_Handler:

    If IsMissing(sFile) Then
        sFile = sFileName
    End If

    Kill (sFileName)
    Exit Sub

ERR_Handler:

    RaiseEvent Error(Err)

End Sub

'****************** class cLog end *****************
Przykładowy kod wykorzystania poniżej:
Sub Logowanie()
    Dim l As New cLog    ' tworzymy obiekt
    l.Delimiter = ","
    l.File = "raport.log"
    l.Log "t", "e", "ee"    ' dodajemy wpis
'    l.KillLog 'w razie czego można skasować
End Sub
ps. Żeby być sprawiedliwym pomysł i pierwowzór zaczerpnąłem z postu Krzysztofa Naworyty z grupy pl.comp.bazy-danych.msaccess. Po chwili zastanowienia przepisałem ją jednak na nowo praktycznie od zera.

sobota, 14 marca 2009

MySQL i procedury

Dziś zdarzyło mi się popełnić procedurę w MySQL-u. O dziwo nawet działa :) ale co mi tam, jest prosta jak budowa cepa i ma zrealizować jedno zadanie: a mianowicie wylosować jeden element z tabeli o nieciągłym numerowaniu w jak najmniejszej ilości prób. A oto Ona

CREATE DEFINER = 'root'@'localhost'
PROCEDURE `new_proc`(
OUT wynik CHAR,
OUT ile INTEGER(11)
)
NOT DETERMINISTIC
READS SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN

declare rnd DOUBLE;
DECLARE ID_element int;
declare ile_elem int;
declare wyn_zap char(20);


select max(id) INTO ile_elem from `documents`;

set ile = 0;

REPEAT

set rnd = RAND() * ile_elem;

set ID_element = rnd;
set ile = ile + 1;
select `tag` INTO wyn_zap
from `documents`
where `documents`.`id` = ID_element
limit 1;

until (wyn_zap is not NULL) end repeat;

set wynik = left(wyn_zap,1);

END;

wtorek, 10 marca 2009

Prosty przykład wykorzystania funkcji chkMach w Excel-u


Function chkMach(sString As String, pattern As String, _
Optional bIgnoreCase As Boolean = True, _
Optional bGlobal As Boolean = True) As Boolean

Dim oRegExp As Object

On Error GoTo ERR_Handler:

If pattern = "" Then
chkMach = False
Exit Function
End If

If sString = "" Then
chkMach = False
Exit Function
End If

Set oRegExp = CreateObject("vbScript.RegExp")
With oRegExp
.IgnoreCase = bIgnoreCase
.Global = bGlobal
.pattern = pattern
chkMach = .Test(sString)
End With

END_Handler:

Set oRegExp = Nothing

Exit Function

ERR_Handler:

chkMach = False

Resume END_Handler:

End Function





Jak widać na załączonym obrazku poprawnie reaguje na wyrażenie regularne.

poniedziałek, 9 marca 2009

Kodowanie Pliku Excel

Pokazałem tu jak można skutecznie zakodować plik Excel-a.

Metoda prosta, lecz niezwykle skuteczna. Działa od Excel-a 2002 wzwyż.