Powershell: Get-History

2018-03-25

Kiedy pracujesz z PowerShell, konsola śledzi i zapamiętuje każdy twój ruch. Dzięki temu można przejrzeć listę wykonywanych do tej pory poleceń naciskając strzałkę w górę. Do przejrzenia wcześniej wykonanych poleceń można sie także posłużyć poleceniem

Get-History

Posiadając listę do tej pory wykonanych poleceń, możesz chcieć ponownie uruchomić jedną z nich. Da się to zrobić powołując się na numer komendy w historii uruchamiając

Invoke-History

Tak to działa w praktyce:

Jeśli chcesz tylko pobrać listę komend i umieścić ją w schowku wykonaj:

Get-History | Select -expand CommandLine | clip

 

 

By Rafał Kraik in Power Shell

SQL: Filestream – dlaczego trzeba go włączyć dwa razy?

2018-03-12

Podczas konfiguracji FILESTREAM dwa razy wykonuje się podobne czynności:

  • W SQL Configuration Manger, należy we właściwościach usługi SQL na karcie FILESTREAM wybrać jedną z dostępnych opcji:
  • A następnie w SQL Management Studio wykonać polecenie SP_CONFIGURE zmieniając 'filestream access level’
    EXEC sp_configure 'filestream access level',2
    GO
    RECONFIGURE
    GO

Czy te dwa kroki się powielają? Czy można wykonać jeden a drugiego już nie?

Otóż nie!

Pierwsza część wykonuje fragment konfiguracji systemu operacyjnego, którego nie można wykonać z wewnątrz procesu SQL

Druga część odpowiada za włączenie opcji na poziomie silnika bazy danych

Pierwsza część wymaga uprawnień lokalnego administratora, a druga sysadmina.

To cały powód!

FILESTREAM Configuration and Setup Changes in SQL Server 2008 February CTP

By Rafał Kraik in SQL

SQL: Jak pracować z FileTable. Konfiguracja bazy, tworzenie tabeli

2018-03-12

FileTable to świetny pomysł na przechowywanie w bazie dokumentów (BLOB), które jednocześnie są dla użytkowników widoczne jako zwykłe pliki na systemie plików.

Żeby FileTable (a ogólniej Filestream) mogły działać odpowiednio należy skonfigurować instancję. We właściwościach usługi SQL Server w SQL Server Configuration Manager należy ustawić FILESTREAM (patrz również tutaj)

Konfigurację wykonujemy również w opcjach serwera:

EXEC sp_configure 'filestream access level'
GO
EXEC sp_configure 'filestream access level',2
GO
RECONFIGURE
GO
EXEC sp_configure 'filestream access level
GO

Pora na utworzenie testowej bazy danych

CREATE DATABASE TestFileTable
GO

Ta baza danych musi posiadać FILE GROUP pozwalający na przechowywanie FILESTREAM

USE TestFileTable
GO
ALTER DATABASE TestFileTable ADD FILEGROUP FG_FileStream CONTAINS FILESTREAM
GO

A z kolei ta grupa musi mieć plik. Zadbaj o to aby usługa SQL miała pełne prawa do katalogu nadrzędnego tutaj C:\SQL

ALTER DATABASE TestFileTable ADD FILE (NAME='F_FileStream', FILENAME='C:\SQL\AdventureWorks_FS') TO FILEGROUP FG_FileStream
GO

Baza będzie przechowywać dokumenty w udostępnianym zasobie o nazwie Docs. Dostęp może być tak jak tu FULL (pliki można modyfikować z poziomu aplikacji np Word, Excel itp), READ_ONLY, lub OFF

ALTER DATABASE TestFileTable SET FILESTREAM (NON_TRANSACTED_ACCESS = FULL, DIRECTORY_NAME='Docs')
GO

Teraz można utworzyć tabelę

CREATE TABLE Manuals AS FILETABLE WITH(FILETABLE_DIRECTORY='Manuals') 
GO

Jeżeli wkopiujesz pliki do katalogu \\computerName\MSSQLSERVER\Docs\Manuals, to w tabeli Manuals pojawią się rekordy. Podobnie usuwanie tych plików spowoduje, że rekordy będą kasowane

SELECT * FROM Manuals
GO

Tabele FileTable można odnaleźć zaglądając do widoków systemowych:

SELECT * FROM sys.filetables; 
GO
SELECT * FROM sys.tables WHERE is_filetable = 1; 
GO 
SELECT object_id, OBJECT_NAME(object_id) AS 'Object Name' 
FROM sys.filetable_system_defined_objects;
GO
SELECT DB_NAME(database_id), non_transacted_access, non_transacted_access_desc
FROM sys.database_filestream_options;
GO

Poziom dostępu do plików w FileTable można zmieniać:

ALTER DATABASE TestFileTable SET FILESTREAM (NON_TRANSACTED_ACCESS = OFF, DIRECTORY_NAME='Docs')
GO
SELECT DB_NAME(database_id), non_transacted_access, non_transacted_access_desc
FROM sys.database_filestream_options;
GO
ALTER DATABASE TestFileTable SET FILESTREAM (NON_TRANSACTED_ACCESS = FULL, DIRECTORY_NAME='Docs')
GO

 

Jeśli rekord zostanie usunięty z tabeli, to zniknie również plik z katalogu

DELETE FROM Manuals WHERE Name = 'New Text Document (2).txt'
GO
SELECT * FROM Manuals
By Rafał Kraik in SQL

SQL: Kolejność wykonywania transakcji

2018-03-11

Tym razem zajmę się kolejnością wykonywania transakcji. Przeanalizujmy taką sytuację:

  • Transakcja A czyta rekord, ale po przeczytaniu rekordu pozostawia na nim lock (czyli np. transakcja pracuje w poziomie izolacji REPEATABLE READ)
  • Transkacja B startuje po transakcji A, i zamierza zmodyfikować ten sam rekord
  • Transakcja C startuje po transakcji B i zamierza przeczytać ten rekord

Pytanie – w jakiej kolejności wykonają się te transakcje?

  • A – B – C, bo w takiej kolejności te transakcje startowały, czy
  • A – C – B, bo transakcja C tylko czyta rekord, tak samo jak transakcja A, czyli nie jest w konflikcie z A. B jako transakcja modyfikująca dane i tak musi czekać, więc nie ma problemu, aby „przepuściła” transakcję „C”

Zacznijmy od potwierdzenia, że jeśli mamy tylko A i C, to bez problemu można uruchomić obie transakcje: Czytaj dalej »

By Rafał Kraik in SQL

SQL: Cannot resolve the collation conflict…

2018-02-25

Zdarza się i to szczególnie wtedy, kiedy baza danych ma inne collation niż serwer/instancja SQL, że wykonywanie zapytania pobierającego dane z jednej bazy i porównującego te dane z danymi z innej bazy, że zapytanie kończy się błędem:

Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Polish_CI_AS" in the equal to operation. 

Collation to parametr zarówno instancji, jak i bazy, jak i każdej kolumny tekstowej jak i nawet poszczególnych zapytań, który określa jak dane są sortowane. Np. można rozróżniać duże i małe litery lub nie. Collation, które rozróżnia wielkość liter ma w nazwie CS (Case Sensitive), a to collation, które nie rozróżnia ma w nazwie CI (Case Insensitive). Collation odpowiada też regułom sortowania zdefiniowanym dla poszczególnych języków, stąd mamy collation angielskie, polskie, chińskie itd. Czytaj dalej »

By Rafał Kraik in SQL

Python: Wyrażenia regularne – moduł re (regex)

2018-02-14

O wyrażeniach regularnych pisałem już tutaj: https://www.mobilo24.eu/wyrazenia-regularne-bardzo-krotki-przewodnik/

Teraz parę słów o wyszukiwaniu w napisie liczb z wykorzystaniem regular expressions (regex) w Pythonie:

Ilekroć chcesz pracować z wyrażeniami regularnymi zacznij od zaimportowania modułu re

import re

Załóżmy, że mamy do czynienia z napisem „OSTP 288” i chcemy wyciągnąć z niego 288. Po kolei należy:

  • korzystając z funkcji re.compile utworzyć prekompilowane wyrażenie regularne
  • korzystając z funkcji re.match przeprowadzić wyszukiwanie wyrażeń pasujących do maski
  • wynik(i) są dostępne za pomocą metody groups(). Jeśli coś zostało znalezione, to wszystkie pasujące dopasowania znajdą się właśnie tutaj
  • a wyrażenie regularne? Tutaj mówi tak
    • .* – ma być dowolny ciąg dowolnych znaków
    • (\d+) – tutaj jest zdefiniowana grupa dopasowania – o tym świadczą () – i tu zostanie zakwalifikowana jedna lub więcej + cyfra \d
    • .* – a potem ma być znowu dowolna ilość dowolnych znaków:
a_text="OSTP 288"
re_expression = re.compile('.*(\d+).*')
re_result = re.match(re_expression,a_text)
re_result.groups()

To teraz przyjmijmy że mamy do czynienia z napisem '1234/5678′. Chcemy wydobyć liczby przed i po /. Właściwie czynności do wykonania są takie same, może tylko wyrażenie regularne wymaga małego wyjaśnienia:

  • (\d+) – pierwsza grupa dopasowania zbudowana tak samo jak poprzednio
  • / – czyli jawnie podany znak jaki musi występować po pierwszej odkrytej liczbie
  • (\d+) – druga grupa dopasowania
  • Zauważ, że nie dopuszczamy występowania w napisie jakichkolwiek innych znaków poza liczbą, ukośnikiem i liczbą
a_text = '1234/5678'
re_expression = re.compile('(\d+)/(\d+)')
re_result = re.match(re_expression,a_text)
re_result.groups()

I ostatni przykład. Tu mamy tekst 'The price for 10 pieces is 330 USD’ i chcemy z niego wydobyć cenę 330. Logika postępowania taka sama jak poprzednio, a wyrażenie regularne:

  • .* – dowolna ilość dowolnych znaków
  •  – spacja
  • (\d+) – grupa dopasowania
  •  USD$ – spacja, napis USD i na tym koniec tekstu. Nic więcej tam nie może występować – to właśnie znaczenie znaku $
a_text = 'The price for 10 pieces is 330 USD'
re_expression = re.compile('.* (\d+) USD$')
re_result = re.match(re_expression,a_text)
re_result.groups()

 

By Rafał Kraik in Python

Python: Odczyt pliku CSV

2018-02-03

Załóżmy, że w pliku cities.csv znajduje sie następujący tekst

CityName,Number,YesNo
New York,80,0
San Francisco,95,1
Paris,95,0
Rome,100,1

czyli mamy do czynienia ze standardowym plikiem Comma Separated Values (CSV)

Żeby rozpocząć pracę z plikiem CSV zaimportuj najpierw moduł csv. Funkcja, która rzeczywiście wczyta i zinterpretuje plik CSV to csv.reader. Generalnie posiadając przetworzony przez reader plik w zmiennej, właściwie nic więcej nie trzeba. Problemem może być tylko to, że obiekt zwracany przez reader jest iteratorem, czyli można po nim „przejść” tylko jeden raz. Jeśli Twój plan to przetworzenie danych wiele razy i na różne sposoby, to można skonwertować do listy. Dlatego początek programu mógłby wyglądać tak:

import csv
with open('C:\\temp\\cities.csv', newline='') as csvfile:
 content = csv.reader(csvfile, delimiter=',', quotechar='|')
 contentList = list(content)

Jeśli chcesz „przejść” przez ten plik i wyświetlać tylko zerową kolumnę to można to zrobić tak:

print("Just column 0-----------------------")
 for row in contentList:
 print(row[0])
 

a ponieważ dane są zapisane w liście, to iteracja jest możliwa po raz drugi: Czytaj dalej »

By Rafał Kraik in Python