niedziela, 31 grudnia 2017

[PL] SQL Server 2014 SP2 - kolumny wyliczane (computed columns)

SQL Server pozwala na tworzenie kolumn nazywanych computed columns, czyli - w wolnym tłumaczeniu - kolumn wyliczanych. Jak to działa w praktyce?

Na potrzeby szkoleniowe, utwórzmy przykładową tabelę składającą się z trzech kolumn:
  • CENA_W_ZL - przeznaczoną na cenę w polskich złotych 
  • KURS_DOLARA_W_ZL - zawierającą kurs dolara podany w polskich złotych 
  • CENA_W_DOLARACH - jest to kolumna typu computed columns, której wartość jest generowana automatycznie poprzez mnożenie wartości znajdujących się w dwóch wcześniej wspomnianych kolumnach

USE tempdb
go
 
CREATE TABLE [dbo].[CENY] (
id int identity(1,1) not null primary key,
CENA_W_ZL smallmoney,
KURS_DOLARA_W_ZL smallmoney,
CENA_W_DOLARACH AS [CENA_W_ZL] * [KURS_DOLARA_W_ZL]
)
Następnie wstawmy przykładowy wiersz do tabeli i sprawdzamy jej zawartość:

INSERT INTO [dbo].[CENY] (CENA_W_ZL, KURS_DOLARA_W_ZL) 
VALUES (100.20,3.60);

SELECT * FROM DBO.CENY

Naszym oczom powinna ukazać się obliczona automatycznie zawartość kolumny CENA_W_DOLARACH jako wynik mnożenia zawartości kolumny CENA_W_ZL i KURS_DOLARA_W_ZL.
 


W przedstawionym powyżej przykładzie wartość kolumny CENA_W_DOLARACH jest za każdym razem wyliczana w momencie, kiedy chcemy poznać jej wartość - czyli wartość nie znajduje się zapisana na stałe w bazie danych. Jeżeli chcielibyśmy zapisać wartość kolumny wyliczanej w bazie danych, w definicji tabeli, przy tego typu kolumnie powinniśmy umieścić  PERSISTED.

poniedziałek, 25 grudnia 2017

[PL] SQL Server 2014 SP2 - klauzula .WRITE w poleceniu UPDATE

W tym wpisie omówię pokrótce na przykładach działanie opcji .WRITE w poleceniu UPDATE. Ogólna składnia wspomnianej klauzuli jest następująca:

.WRITE (expression,@Offset,@Length)

Na początek zwracam uwagę, że polecenie .WRITE współpracuje z kolumnami typu varchar(max), nvarchar(max), varbinary(max)

Na potrzeby szkoleniowe utwórzmy sobie tabelę i wprowadźmy do niej przykładowe dane

CREATE TABLE Test01 (
Id INT PRIMARY KEY NOT NULL, 
Tekst varchar(max) NOT NULL
);

INSERT INTO Test01 (Id, Tekst) VALUES (1, 'To jest nasz testowy tekst');

Sprawdźmy aktualną zawartość tabeli:

SELECT * FROM Test01 



Wykonajmy UPDATE z użyciem .WRITE, który spowoduje dodanie tekstu "TEN TEKST ZOSTANIE DODANY NA POCZĄTKU" na początku wyrażenia "To jest nasz testowy tekst", gdzie 0 jako wartość @Offset oznacza, że wprowadzamy tekst na początku wyrażenia., z kolei 0 jako parametr dla @Length oznacza, że wstawiamy dodatkowy tekst, a nie zastępujemy istniejący. 

UPDATE Test01 SET Tekst .WRITE ('TEN TEKST ZOSTANIE DODANY NA POCZĄTKU ',0,0) WHERE Id = 1;

Sprawdźmy aktualną zawartość tabeli:

SELECT * FROM Test01 



W kolejnym przykładzie dodajmy tekst na końcu istniejącego wyrażenia. Służy do tego NULL jako wartość @Offset i wówczas zawartość pola @Length nie jest sprawdzana. 

UPDATE Test01 SET Tekst .WRITE (' TEN TEKST ZOSTANIE DODANY NA KOŃCU',NULL,0) WHERE Id = 1;

Wyświetlmy  aktualną zawartość tabeli:

SELECT * FROM Test01 



W ostatnim ćwiczeniu,  słowo "ten" o długości 3 znaków na pozycji 65 zastąpimy na rzecz "tamten"

UPDATE Test01 SET Tekst .WRITE ('tamten',65,3) WHERE Id = 1;

I zobaczymy bieżącą zawartość tabeli:

SELECT * FROM Test01 


niedziela, 17 grudnia 2017

[EN] SQL Server 2014 SP2 - how works TOP and OFFSET?

The TOP and OFFSET commands allows to display only some of the rows from the table - for example, 5 rows, 5 percent of all rows, or rows from 40 to 50. How to use it in practice?

For beginning, let's create a table with test data.

CREATE TABLE dbo.Cities
(
CityID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
CityName VARCHAR(255) NOT NULL,
Population INT NOT NULL
);

INSERT INTO dbo.Cities (CityName, Population)
VALUES
('Shanghai', 24256800), ('Beijing', 21516000),
('Delhi', 16787941), ('Lagos', 16060303),
('Tianjin', 15200000), ('Karachi', 14910352),
('Chengdu', 14427500), ('Istanbul', 14160467),
('Tokyo', 13513734), ('Guangzhou', 13080500),
('Mumbai', 12442373), ('Moscow', 12380664),
('Sao Paulo', 12038175), ('Lahore', 11126285),
('Shenzhen', 10467400), ('Jakarta', 10075310),
('Seoul', 9995784), ('Wuhan', 9785392);

In the dbo.Cities table there are 18 lines. 

SELECT COUNT(*) FROM dbo.Cities


How do I display 5 rows from all?

SELECT TOP(5) * FROM dbo.Cities


How do I display 5 rows from all, where the population is the smallest?

SELECT TOP(5) * FROM dbo.Cities
ORDER BY POPULATION ASC



How do I display 5 percent rows from all?

SELECT TOP(20) PERCENT * FROM dbo.Cities



How to skip records from 1 to 5 and display only the next 2 records (6.7)?

SELECT * FROM dbo.Cities
order by population desc
OFFSET 5 ROWS FETCH FIRST 2 ROWS ONLY;


How to skip records from 1 to 15 and display all others?

SELECT * FROM dbo.Cities
order by population desc
OFFSET 15 ROWS


sobota, 16 grudnia 2017

[EN] SQL Server 2014 SP2 - surrogate keys

What is it surrogate key? Let us quote the definition contained in wikipedia:

"A surrogate key (or synthetic key, entity identifier, system-generated key, database sequence number, factless key, technical key, or arbitrary unique identifier[citation needed]) in a database is a unique identifier for either an entity in the modeled world or an object in the database. The surrogate key is not derived from application data, unlike a natural (or business) key which is derived from application data." (https://en.wikipedia.org/wiki/Surrogate_key)

In other words, surrogate key is not natural key for rows in the table. The natural key is - for example - social security number or growing number such as 1, 2, 3 etc.  Surrogate key provides unique identifier for rows on database level and not only, not just a single table.

To put on a surrogate key in the table, we create a uniqueidentifier column with default action NEWSEQUENTIALID(). 

USE tempdb
GO

CREATE TABLE table_test01 (
ColumnA uniqueidentifier DEFAULT NEWSEQUENTIALID(),
ColumnB varchar(100)
); 

Then, insert a new row into the table.

INSERT INTO table_test01 (ColumnB) VALUES ('test row');

We check the contents of the table and our eyes will see our surrogate key.

SELECT * FROM table_test01



Second option surrogate key is NEWID() instead NEWSEQUENTIALID(). 

USE tempdb
GO

CREATE TABLE table_test02 (
ColumnA uniqueidentifier DEFAULT NEWID(),
ColumnB varchar(100)
); 

INSERT INTO table_test02 (ColumnB) VALUES ('test row');

SELECT * FROM table_test02


Microsoft not recommended using NEWSEQUENTIALID if  privacy is a concern, because is possible to guess the value of the next generated GUID, but NEWSEQUENTIALID may it can run faster than NEWID().

The disadvantage of surrogate key is its size. One NEWID() value need 16 byes, one BIGINT value need 8 bytes, one INT value need only 4 bytes. 

DECLARE @test03 uniqueidentifier;
SET @test03 = NEWID();
SELECT DATALENGTH(@test03) AS '@test03 - NEWID size in bytes';

DECLARE @test04 bigint;
SET @test04 = 701;
SELECT DATALENGTH(@test04) AS '@bigint - BIGINT size in bytes';

DECLARE @test05 int;
SET @test05 = 701;
SELECT DATALENGTH(@test05) AS '@int - BIGINT size in bytes';


Another option than NEWID and NEWSEQUENTIALID in the uniqueidentifier data type is using SEQUENCE OBJECT. I call them generators. Below is an example.

-- we use command CREATE SEQUENCE 
-- and specify the name of the object 
-- (in our case "first")
-- and the name of the schema in which 
-- it is to be create
-- (in our case: "dbo")
CREATE SEQUENCE dbo.first
-- we define the type of data 
-- for this SEQUENCE OBJECT
-- if not specified, then 
-- BIGINT will be used 
AS INT
-- we define the initial value
START WITH 1
-- we determine how much to grow of object
-- 1 means that it will increase by 1, e.g. 1, 2, 3
INCREMENT BY 1
-- minimum supported value 
-- default it is as minimum data type value
MINVALUE 1
-- we specify that we do not 
-- want after reaching MAXVALUE 
-- (the same as the given data 
-- type predicts by default) 
-- to re-use the object from 
-- the beginning
NO CYCLE;

CREATE TABLE dbo.test05
(
ColumnA INT NOT NULL PRIMARY KEY,
ColumnB VARCHAR(255)
);

INSERT INTO dbo.test05
(ColumnA, ColumnB)
VALUES
(NEXT VALUE FOR dbo.first, 'test');

SELECT * FROM test05


We can use one sequene object in many tables. This will ensure the uniqueness of the rows at the database level. In one sequence object we can save as much data as the BIGINT data type allows - from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. 

sobota, 23 września 2017

[EN] Vista SP2 / Firefox 53 - how resolve error about unsupported MIME format

If on the website with video in MP4 format, you see a message about unsupported MIME format, you should install KB2117917 to resolve this issue. 

This solution worked in my case - with Windows Vista SP2 x64 Home Premium and Mozilla Firefox 52.3.0 (32-bit).

niedziela, 28 maja 2017

[EN] SQL Server 2014 SP2 - Processing data from XML file using OPENXML

Microsoft SQL Server offers opportunity work with data in XML format. One of the T-SQL functions is OPENXML, which allows to navigate through the XML file structure to process the information it contains. The XML file may be loaded into the database using - for example - OPENROWSET. 

In this entry, I show how to import data from an XML file into a database and then display the content of the selected node of XML file.  For training purposes I will use the XML file provided by the National Health Fund, which contains information on blocked prescriptions numbers. This file is possible to download from website http://recepty.nfz.gov.pl/ under the link "pobierz komunikat XML - rozwinięty".


(to see the full size image click on it)

The *.ARZ file will be downloaded. From this ARZ we can extract XML file.



This XML file contains a simple structure.


(to see the full size image click on it)

In order to import the XML file (/komunikat/blokada/zakres-nr/nr-recepty node)  into the database and display its contents as a list of blocked prescriptions numbers, we can use the following script.

DECLARE @idoc int;

DECLARE @out XML;
SELECT @out=BulkColumn
FROM 
OPENROWSET (BULK 'C:\xml\20170528_1557_rozwiniety.xml',SINGLE_BLOB) as import
EXEC sp_xml_preparedocument @idoc OUTPUT, @out;  
SELECT *  
FROM  OPENXML (@idoc, '/komunikat/blokada/zakres-nr/nr-recepty',0) WITH (
numer varchar(255) 
);  

Effect


(to see the full size image click on it)

For more information about OPENXML see offical Microsoft documentation of T-SQL: https://docs.microsoft.com/en-us/sql/t-sql/functions/openxml-transact-sql

niedziela, 1 stycznia 2017

[PL] Windows Server 2008 R2 SP1 - podłączenie stacji roboczej do domeny bez dostępu do sieci

Windows Server 2008 R2 umożliwia tzw. offline domain join, czyli podłączenie stacji roboczej do domeny w sytuacji, gdy przyłączany komputer nie posiada aktualnie połączenia z kontrolerem domeny. 

Poniżej zamieszczam krótki opis w jaki sposób można skorzystać z tej metody na przykładzie kontrolera domeny z Windows Server 2008 R2 SP1 x64 Enterprise oraz Windows 8.1 Enterprise x64.

Na serwerze: 

djoin 
/PROVISION 
/DOMAIN "wroblewski.local" 
/MACHINE "AW-TEST" 
/SAVEFILE "C:\test_offline_join\AW-TEST"


Na kliencie:

djoin 
/REQUESTODJ 
/LOADFILE "C:\test_offline_join\AW-TEST" 
/WINDOWSPATH "c:\windows" 
/LOCALOS



Efekt: