2015-03-17
Reporting Services pozwala na zautomatyzowanie wysyłania raportów dla użytkowników. Czasami jednak zdarza się, że raport, który ma być dostarczony jest pusty, lub się nie zmienił od poprzedniego razu. W aktualnej wersji SSRS nie ma opcji, która by to uwzględniała. Trzeba się odwołać do sztuczek.
Utwórz raport i schedule, który się już nie będzie automatycznie uruchamiał. W tym momencie SSRS tworzy job w SQL Agent, który uruchamia się wg schedule. Nazwa tego joba jest niezbyt przyjaznym UID-em
Stwórz własny job, który sprawdza, czy raport ma być wykonany. Wbuduj tu własną logikę. Sprawdź czy dane są, albo czy się zmieniły itp. Jeżeli warunek jest spełniony uruchom job stworzony przez SSRS!
Polecenie, które pozwoli skojarzyć konkretny raport z jobem:
SELECT
Sch.ScheduleId AS 'Name of Job’,
Sch.LastRunTime,
U.UserName AS 'Created by’,
Cat.Name AS 'Report name’
FROM [dbo].[Schedule] Sch
JOIN [dbo].[ReportSchedule] RSch ON Sch.ScheduleId = Sch.ScheduleId
JOIN [dbo].[Catalog] Cat ON Cat.ItemId = RSch.ReportId
JOIN dbo.Users U ON Sch.CreatedById = U.UserId
Do uruchomienia joba z wykorzystaniem TSQL można wykorzystać następujący fragment kodu:
USE msdb ;
GO
EXEC dbo.sp_start_job N’Weekly Sales Data Backup’ ;
GO
Szczegóły dot. uruchamiania jobów z TSQL: https://msdn.microsoft.com/en-us/library/ms190774.aspx
2015-03-09
Problem: Chcesz zalogować do tabeli polecenia jakimi użytkownicy modyfikują dane.
Komentarz: Możesz skorzystać z profilera, sesji eventów, ale jeśli chcesz to zrobić triggerem….
Rozwiązanie:
Załóżmy, że tabela, na której są wykonywane polecenia wygląda następująco:
CREATE TABLE TestTable
(ID INT IDENTITY PRIMARY KEY,
SomeData NVARCHAR(50))
GO
Stwórz tabelę do zapisywania komend użytkowników:
CREATE TABLE SQLCommands
(ID INT IDENTITY PRIMARY KEY,
SQLCmd NVARCHAR(4000))
GO
Pora na trigger:
CREATE TRIGGER tr_TestTable ON TestTable FOR INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON
DECLARE @SQLCmd NVARCHAR(4000)
DECLARE @TEMP TABLE
(EventType NVARCHAR(30), Parameters INT, EventInfo NVARCHAR(4000))
INSERT INTO @TEMP EXEC(’DBCC INPUTBUFFER(@@SPID) WITH NO_INFOMSGS’)
SELECT @SQLCmd = EventInfo FROM @TEMP
INSERT SQLCommands VALUES (@SQLCmd)
END
Co się tutaj dzieje:
- SET NOCOUNT ON powoduje, że podczas wykonywania triggera nic nie będzie dodatkowo wyświetlane na ekranie.
- DECLARE @SQLCmd… to zmienna, do której na chwilę trafi polecenie
- DECLARE @Temp … to deklaracja zmiennej tablicowej, która za chwilę będzie przechowywać wynik polecenia DBCC
- INSERT… wkłada do tabeli @Temp wynik polecenia DBCC INPUTBUFFER(@@SPID) WITH NO_INFOMSGS
- SELECT @SQLCmd = EventInfo FROM @TEMP – treść przechwyconego polecenia SQL jest wpisywane do zmiennej @SQLCmd
- I końcowy INSERT – zapisanie zmiennej @SQLCmd w stałej tabeli SQLCommands.
Pora przetestować rozwiązanie:
INSERT TestTable VALUES(’x’)
GO
UPDATE TestTable SET SomeData = 'y’
GO
DELETE FROM TestTable
GO
I sprawdzenie wyniku:
SELECT * FROM SQLCommands

Źródło: http://sqlblog.com/blogs/jonathan_kehayias/archive/2010/01/11/tsql2sday-using-sys-dm-exec-sql-text-to-get-the-calling-statement.aspx
2015-03-06
Jeśli pracujesz z powershell wewnątrz firmowej sieci, to zapewne od Internetu odgradza cię proxy. Proxy może wymagać uwierzytelnienia. W takim przypadku komenda Update-Help zawodzi i pozostaje korzystać z opcji -Online podczas używania komendy Get-Help, dzięki czemu help wyświetla się w przeglądarce www.
Ale mamy też inne rozwiązanie. Załóżmy przez chwilę, że chcesz pobrać plik dostępny pod linkiem HTTP. W Powershell można to zrobić w następujący sposób:
$wc = New-Object System.Net.WebClient
$wc.DownloadString(’http://mobilo24.eu’)
Jeśli jesteś za authenticated proxy, to komenda skończy się błędem:
Exception calling „DownloadString” with „1” argument(s): „Serwer zdalny zwrócił błąd: (407) Wymagane uwierzytelnianie serwera pro
xy.”
At line:1 char:1
+ $wc.DownloadString(’http://microsoft.com’)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
No cóż, trzeba pokazać obiektowi WebClient, że należy korzystać z Proxy. Spróbuj tak:
$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
Teraz poleceniepobrania strony kończy się sukcesem:
$wc.DownloadString(’http://mobilo24.eu’)
Ale to nie wszystko. Okazuje się, że… Update-Help też zaczyna działać!!! Dlatego jeśli za authenticated proxy chcesz zaktualizaować helpa wykonaj:
$wc = New-Object System.Net.WebClient
$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
Update-Help
Nie zapomnij przy tym uruchmić powershella „jako administrator”.
Źródła:
http://itgeeks.eu/powershell/using-powershell-from-behind-authenticated-proxy/
http://blog.stangroome.com/2013/08/02/powershell-update-help-and-an-authenticating-proxy/
2015-03-05
Załóżmy, że chcesz mieć listę wartości i dynamicznie dodawać do niej elementy:
$list = @(„a”,”b”)
$list.Add(„c”)
Niestety, próba dodania elementu kończy się błędem:
Exception calling „Add” with „1” argument(s): „Rozmiar kolekcji jest stały.”
At line:1 char:1
+ $list.Add(„a”)
+ ~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : NotSupportedException
Wszystko dlatego, że lista ma stały rozmiar, co sprawdzisz:
$list.IsFixedSize
Jak obejść problem?
Rozwiązanie 1:
Dodawaj elementy wykorzystując operator += zamiast metodę Add:
$list+=”x”

Rozwiązanie 2:
Skorzystaj z [System.Collections.ArrayList]. Ten typ nie jest stałego rozmiaru i pozwala na dodawanie nowych elementów.
[System.Collections.ArrayList]$ArrayList = @()
$ArrayList.Add(„a”)
$ArrayList.Add(„b”)
$ArrayList.Add(„c”)
2015-03-05
W Powershell można weryfikować, czy napis „pasuje” do wyrażenia regularnego korzystając z typu [regex] oraz jego metody IsMatch.
Z drugiej strony, definiując parametry funkcji możesz weryfikować poprawność parametru korzystając z ValidateScript.
Jak sprawdzić, czy parametr przychodzący do funkcji jest zgodny z wyrażeniem regularnym?
Oto propozycja:
- Parametrem jest $phone, który ma być numerem telefonu rozpoczynającym się od „+48 ” lub „0048 „
- Wyrażenie regularne opisujące takie numery telefonu to [regex]”\+48 [0-9]{9}|0048 [0-9]{9}”
- W ValidateScript tworzymy zmienną $mask, która jest wyrażeniem regularnym
- Następnie sprawdzamy wywołując $match.IsMatch, czy przekazywana wartość czyli $_ pasuje do wyrażenia
- To sprawdzenie zwraca $true – udało się lub $false – był błąd
[ValidateScript({$mask = [regex]”\+48 [0-9]{9}|0048 [0-9]{9}”; $mask.IsMatch($_) })][string]$phone=’+48 123456789′
$phone = '123456789′ # ERROR !!!!
$phone = ’0048 123456789′ # OK 🙂
2015-03-01
W kontenerze ForEach odbywa się kopiowanie plików, które jest narażone na błędy. Chciałbyś zapisać gdzieś informację o błędzie, ale nie przerywać kopiowania. Jak to zrobić, poza globalną zmianą wyłączającą wszelkie śledzenie plików. Sytuacja wejściowa wygląda następująco:

Pętla (count and copy files) wykonywana jest dla każdego pliku, a po jej zakończeniu może być wyświetlone podsumowanie (Summary). W ramach pętli najpierw zliczamy ilość plików (Count files) do specjalnie w tym celu zadeklarowanej zmiennej, następnie próbujemy skopiować plik (Copy file), potem w zależności od tego czy się udało, czy nie wykonujemy pewne czynności: Script on success, gdy się udało lub Script on failure, gdy doszło do błędu. Czytaj dalej »
2015-02-28
Jeśli pakiet SSIS ma zapisywać dane do skoroszytu Excel, to podczas definiowania docelowego arkusza możesz napotkać bład:
There is no sufficient information about mapping SSIS types to data types of the selected .NET data provider.
As a result, you may need to modify the default column types of the SQL statement on the next screen.
Ten tajemnicy komunikat mówi najczęściej o tym, że do Excela próbujesz skierować dane, których typów Excel nie rozumie. Przykładem może być typ TIME. Istnieje w SQL, ale Excel go nie zna. Podobnie typ rowguid.
Aby pozbyć się tego błędu pozbądź się kłopotliwych kolumn (jeżeli nie są potrzebne) lub zmień ich typ korzystając np z Derived Column.