sql >> Databasteknik >  >> RDS >> PostgreSQL

En översikt över JSON-funktioner inom PostgreSQL

Vad är JSON?

JSON står för "JavaScript Object Notation" som är en typ av dataformat som populärt används av webbapplikationer. Detta innebär att data skulle överföras mellan webbapplikationer och servrar i ett sådant format. JSON introducerades som ett alternativ till XML-formatet. På "gamla goda dagar" användes data för att överföras i XML-format som är en tung datatyp jämfört med JSON. Nedan är ett exempel på JSON-formaterad sträng:

{ "ID":"001","name": "Ven", "Country": "Australia",  "city": "Sydney", "Job Title":"Database Consultant"}

En JSON-sträng kan innehålla ett annat JSON-objekt i sig själv som visas nedan:

{ "ID":"001", "name": "Ven", "Job Title":"Database Consultant", "Location":{"Suburb":"Dee Why","city": "Sydney","State":"NSW","Country": "Australia"}}

Moderna webb- och mobilapplikationer genererar mestadels data i JSON-format, även kallade "JSON-bytes", som plockas upp av applikationsservrarna och skickas till databasen. JSON-byten bearbetas i sin tur, delas upp i separata kolumnvärden och infogas i en RDBMS-tabell.
Exempel:

{ "ID":"001","name": "Ven", "Country": "Australia",  "city": "Sydney", "Job Title":"Database Consultant"}

Ovan JSON-data konverteras till en SQL som nedan...

Insert into test (id, name, country,city,job_title) values  (001,'Ven','Australia','Sydney','Database Consultant');

När det gäller att lagra och bearbeta JSON-data finns det olika NoSQL-databaser som stöder det och den mest populära är MongoDB. När det gäller RDBMS-databaser, fram till nyligen, behandlades JSON-strängar som normal text och det fanns inga datatyper som specifikt känner igen, lagrar eller bearbetar JSON-formatsträngar. PostgreSQL, den mest populära RDBMS-databasen med öppen källkod, har kommit med JSON-datatyp som visade sig vara mycket fördelaktig för prestanda, funktionalitet och skalbarhet när det gäller att hantera JSON-data.

PostgreSQL + JSON

PostgreSQL-databas har blivit mer och mer populär ända sedan JSON-datatypen introducerades. Faktum är att PostgreSQL har överträffat MongoDB när det gäller att bearbeta en stor mängd JSON-data. Applikationerna kan lagra JSON-strängar i PostgreSQL-databasen i standard JSON-format. Utvecklare behöver bara berätta för applikationen att skicka över JSON-strängarna till databasen som en json-datatyp och hämta tillbaka i JSON-formatet. Lagring av JSON-sträng i JSON-datatyp har flera fördelar jämfört med att lagra densamma i TEXT-datatyp. JSON-datatyp kan endast acceptera giltiga JSON-formaterade strängar, om strängen inte är i korrekt JSON-format genereras ett fel. JSON-datatyp hjälper applikationen att utföra effektiva och indexbaserade sökningar som vi kommer att se i detalj inom kort.

JSON-datatypen introducerades i PostgreSQL-9.2-posten, där betydande förbättringar gjordes. Det stora tillägget kom upp i PostgreSQL-9.4 med tillägget av JSONB-datatyp. JSONB är en avancerad version av JSON-datatypen som lagrar JSON-data i binärt format. Detta är den stora förbättringen som gjorde stor skillnad för hur JSON-data söktes och bearbetades i PostgreSQL. Låt oss ta en detaljerad titt på fördelarna med JSON-datatyper.

JSON- och JSONB-datatyper

JSON-datatyp lagrar json-formaterade strängar som en text som inte är särskilt kraftfull och inte stöder många JSON-relaterade funktioner som används för sökningar. Den stöder endast traditionell B-TREE-indexering och stöder inte andra indextyper som är absolut nödvändiga för snabbare och effektivare sökoperationer över JSON-data.

JSONB, den avancerade versionen av JSON-datatypen, rekommenderas starkt för lagring och bearbetning av JSON-dokument. Den stöder ett brett utbud av json-operatörer och har många fördelar jämfört med JSON, som att lagra JSON-formaterade strängar i binärt format och stödja JSON-funktioner och indexering för att utföra effektiva sökningar.

Låt oss titta på skillnaderna.

  JSON JSONB
1 Ganska mycket som en TEXT-datatyp som endast lagrar ett giltigt JSON-dokument. Lagrar JSON-dokumenten i binärt format.
2 Lagrar JSON-dokumenten som de är inklusive blanksteg. Trimmar av vita utrymmen och lagrar i ett format som främjar snabbare och effektivare sökningar
3 Stöder inte indexering av FULLTEXT-SEARCH Stöder indexering av FULLTEXT-SEARCH
4 Stöder inte många olika JSON-funktioner och -operatörer Stöder alla JSON-funktioner och operatörer

Exempel för #4 listad ovan

JSON

Nedan finns en tabell med JSON-datatyp

dbt3=# \d product
                   Table "dbt3.product"
     Column     |  Type  | Collation | Nullable | Default
----------------+--------+-----------+----------+---------
 item_code      | bigint |           | not null |
 productdetails | json   |           |          |
Indexes:
    "product_pkey" PRIMARY KEY, btree (item_code)

Stöder inte traditionella JSON-operatörer (som "@>" eller "#>"). Fulltextsökning genom JSON-data görs med "@>" eller "#>" i en SQL som inte stöds av JSON-datatypen

dbt3=# select * from product where productdetails @> '{"l_shipmode":"AIR"}' and productdetails @> '{"l_quantity":"27"}';
ERROR:  operator does not exist: json @> unknown
LINE 1: select * from product where productdetails @> '{"l_shipmode"...
                                                   ^
HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.
dbt3=#

JSONB

Nedan finns en tabell med JSONB-datatyp

dbt3=# \d products
                  Table "dbt3.products"
    Column     |  Type  | Collation | Nullable | Default
---------------+--------+-----------+----------+---------
 item_code     | bigint |           | not null |
 order_details | jsonb  |           |          |
Indexes:
    "products_pkey" PRIMARY KEY, btree (item_code)

Stöder FULLTEXTSÖKNING genom JSON-data med operatorer (som "@>")

dbt3=# select * from products where order_details @> '{"l_shipmode" : "AIR"}' limit 2;
 item_code |                                                                                        order_details
-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         4 | {"l_partkey": 21315, "l_orderkey": 1, "l_quantity": 28, "l_shipdate": "1996-04-21", "l_shipmode": "AIR", "l_commitdate": "1996-03-30", "l_shipinstruct": "NONE", "l_extendedprice": 34616.7}
         8 | {"l_partkey": 42970, "l_orderkey": 3, "l_quantity": 45, "l_shipdate": "1994-02-02", "l_shipmode": "AIR", "l_commitdate": "1994-01-04", "l_shipinstruct": "NONE", "l_extendedprice": 86083.6}
(2 rows)
Ladda ner Whitepaper Today PostgreSQL Management &Automation med ClusterControlLäs om vad du behöver veta för att distribuera, övervaka, hantera och skala PostgreSQLDladda Whitepaper

Hur man frågar efter JSON-data

Låt oss ta en titt på några PostgreSQL JSON-funktioner relaterade till dataoperationer. Nedan är hur JSON-data ser ut i en tabell. Kolumnen "order_details" är av typen JSONB

dbt3=# select * from product_details ;
 item_code |                                                                                                 order_details
-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         1 | {"l_partkey": 1551894, "l_orderkey": 1, "l_quantity": 17, "l_shipdate": "1996-03-13", "l_shipmode": "TRUCK", "l_commitdate": "1996-02-12", "l_shipinstruct": "DELIVER IN PERSON", "l_extendedprice": 33078.9}
         2 | {"l_partkey": 673091, "l_orderkey": 1, "l_quantity": 36, "l_shipdate": "1996-04-12", "l_shipmode": "MAIL", "l_commitdate": "1996-02-28", "l_shipinstruct": "TAKE BACK RETURN", "l_extendedprice": 38306.2}
         3 | {"l_partkey": 636998, "l_orderkey": 1, "l_quantity": 8, "l_shipdate": "1996-01-29", "l_shipmode": "REG AIR", "l_commitdate": "1996-03-05", "l_shipinstruct": "TAKE BACK RETURN", "l_extendedprice": 15479.7}
         4 | {"l_partkey": 21315, "l_orderkey": 1, "l_quantity": 28, "l_shipdate": "1996-04-21", "l_shipmode": "AIR", "l_commitdate": "1996-03-30", "l_shipinstruct": "NONE", "l_extendedprice": 34616.7}
         5 | {"l_partkey": 240267, "l_orderkey": 1, "l_quantity": 24, "l_shipdate": "1996-03-30", "l_shipmode": "FOB", "l_commitdate": "1996-03-14", "l_shipinstruct": "NONE", "l_extendedprice": 28974}
         6 | {"l_partkey": 156345, "l_orderkey": 1, "l_quantity": 32, "l_shipdate": "1996-01-30", "l_shipmode": "MAIL", "l_commitdate": "1996-02-07", "l_shipinstruct": "DELIVER IN PERSON", "l_extendedprice": 44842.9}
         7 | {"l_partkey": 1061698, "l_orderkey": 2, "l_quantity": 38, "l_shipdate": "1997-01-28", "l_shipmode": "RAIL", "l_commitdate": "1997-01-14", "l_shipinstruct": "TAKE BACK RETURN", "l_extendedprice": 63066.3}
         8 | {"l_partkey": 42970, "l_orderkey": 3, "l_quantity": 45, "l_shipdate": "1994-02-02", "l_shipmode": "AIR", "l_commitdate": "1994-01-04", "l_shipinstruct": "NONE", "l_extendedprice": 86083.6}
         9 | {"l_partkey": 190355, "l_orderkey": 3, "l_quantity": 49, "l_shipdate": "1993-11-09", "l_shipmode": "RAIL", "l_commitdate": "1993-12-20", "l_shipinstruct": "TAKE BACK RETURN", "l_extendedprice": 70822.1}
        10 | {"l_partkey": 1284483, "l_orderkey": 3, "l_quantity": 27, "l_shipdate": "1994-01-16", "l_shipmode": "SHIP", "l_commitdate": "1993-11-22", "l_shipinstruct": "DELIVER IN PERSON", "l_extendedprice": 39620.3}
(10 rows)

Välj alla artikelkoder inklusive deras leveransdatum

dbt3=# select item_code, order_details->'l_shipdate' as shipment_date from product_details ;

 item_code | shipment_date
-----------+---------------
         1 | "1996-03-13"
         2 | "1996-04-12"
         3 | "1996-01-29"
         4 | "1996-04-21"
         5 | "1996-03-30"
         6 | "1996-01-30"
         7 | "1997-01-28"
         8 | "1994-02-02"
         9 | "1993-11-09"
        10 | "1994-01-16"
(10 rows)

Få item_code, kvantitet och pris på alla beställningar som kommit med flyg

dbt3=# select item_code, order_details->'l_quantity' as quantity, order_details->'l_extendedprice' as price, order_details->'l_shipmode' as price from product_details where order_details->>'l_shipmode'='AIR';

 item_code | quantity |  price  | price
-----------+----------+---------+-------
         4 | 28       | 34616.7 | "AIR"
         8 | 45       | 86083.6 | "AIR"
(2 rows)

JSON-operatorerna "->" och "->>" används för urval och jämförelser i SQL-frågan. Operatorn "->" returnerar JSON-objektfältet som ett fält inom citattecken och operatorn "->>" returnerar JSON-objektfältet som TEXT. Ovanstående två SQL:er är exempel på att visa JSON-fältvärden som de är. Nedan är ett exempel på att extrahera JSON-fältet i TEXT-formuläret.
Nedan är ett exempel på att hämta JSON-fältet i form av TEXT

dbt3=# select item_code, order_details->>'l_shipdate' as shipment_date from product_details ;
 item_code | shipment_date
-----------+---------------
         1 | 1996-03-13
         2 | 1996-04-12
         3 | 1996-01-29
         4 | 1996-04-21
         5 | 1996-03-30
         6 | 1996-01-30
         7 | 1997-01-28
         8 | 1994-02-02
         9 | 1993-11-09
        10 | 1994-01-16
(10 rows)

Det finns en annan operatör som heter "#>" som används för att fråga datadelen av ett JSON-element som i sin tur är en del av en JSON-sträng. Låt oss titta på ett exempel.
Nedan är data i tabellen.

dbt3=# select * from test_json ;
  id   |                                                                                                details
-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 10000 | {"Job": "Database Consultant", "name": "Venkata", "Location": {"city": "Sydney", "State": "NSW", "Suburb": "Dee Why", "Country": "Australia"}}
 20000 | {"Job": "Database Consultant", "name": "Smith", "Location": {"city": "Sydney", "State": "NSW", "Suburb": "Manly", "Country": "Australia"}}
 30000 | {"Job": "Developer", "name": "John", "Location": {"city": "Sydney", "State": "NSW", "Suburb": "Brookvale", "Country": "Australia"}}
 50000 | {"cars": {"Ford": [{"doors": 4, "model": "Taurus"}, {"doors": 4, "model": "Escort"}], "Nissan": [{"doors": 4, "model": "Sentra"}, {"doors": 4, "model": "Maxima"}, {"doors": 2, "model": "Skyline"}]}}
 40000 | {"Job": "Architect", "name": "James", "Location": {"city": "Melbourne", "State": "NSW", "Suburb": "Trugnania", "Country": "Australia"}}

Jag vill se alla detaljer med "State" "NSW" och "State" är JSON-objektnyckeln som är en del av nyckeln "Location". Nedan är hur du frågar detsamma.

dbt3=# select * from test_json where details #> '{Location,State}'='"NSW"';
  id   |                                                                    details
-------+------------------------------------------------------------------------------------------------------------------------------------------------
 10000 | {"Job": "Database Consultant", "name": "Venkata", "Location": {"city": "Sydney", "State": "NSW", "Suburb": "Dee Why", "Country": "Australia"}}
 20000 | {"Job": "Database Consultant", "name": "Smith", "Location": {"city": "Sydney", "State": "NSW", "Suburb": "Manly", "Country": "Australia"}}
 30000 | {"Job": "Developer", "name": "John", "Location": {"city": "Sydney", "State": "NSW", "Suburb": "Brookvale", "Country": "Australia"}}
 30000 | {"Job": "Architect", "name": "James", "Location": {"city": "Melbourne", "State": "NSW", "Suburb": "Trugnania", "Country": "Australia"}}
(4 rows)

Aritmetiska operationer kan utföras på JSON-data. Typcasting behövs eftersom datadelen av JSON-kolumnen är TEXT.

dbt3=# select item_code, order_details->'l_quantity' as quantity, order_details->'l_extendedprice' as price, order_details->'l_shipmode' as price from product_details where (order_details->'l_quantity')::int > 10;
 item_code | quantity |  price  |  price
-----------+----------+---------+---------
         1 | 17       | 33078.9 | "TRUCK"
         2 | 36       | 38306.2 | "MAIL"
         4 | 28       | 34616.7 | "AIR"
         5 | 24       | 28974   | "FOB"
         6 | 32       | 44842.9 | "MAIL"
         7 | 38       | 63066.3 | "RAIL"
         8 | 45       | 86083.6 | "AIR"
         9 | 49       | 70822.1 | "RAIL"
        10 | 27       | 39620.3 | "SHIP"
(9 rows)

Bortsett från allt ovanstående kan följande operationer också utföras på JSON med SQLs inklusive JOINs

  1. Sortering av data med hjälp av ORDER BY-satsen
  2. Aggregation med aggregerade funktioner som SUM, AVG, MIN, MAX etc.
  3. Gruppera data med hjälp av GROUP BY-satsen

Vad sägs om prestanda?

Data i JSON-kolumner kommer att vara av text och baserat på datastorleken kan prestandaproblem förväntas. Sökningar genom JSON-data kan ta tid och beräkningskraft vilket resulterar i långsamma svar på applikationen/apparna. Det är absolut nödvändigt för DBA:er att säkerställa att SQL:er som träffar JSON-kolumnerna svarar tillräckligt snabbt och ger bra prestanda. Eftersom dataextraheringen görs via SQL, är alternativet DBA:erna skulle leta efter möjligheten att indexera och ja, JSON-datatyper stöder indexeringsalternativ.

Låt oss ta en titt på indexeringsalternativen som JSON ger oss.

Indexering av JSONB

JSONB-datatypen stöder indexering av FULLTEXT-SEARCH. Detta är den viktigaste förmågan hos JSONB som DBA:er kommer att se fram emot när de använder JSONB-datatyper. Ett normalt index på en JSON-objektnyckel kanske inte hjälper när du använder JSON-specifika operatorer i sökfrågorna. Nedan finns en TEXTSEARCH-fråga som används för en HELA TABELL-SCANNING

dbt3=# explain select * from products where order_details @> '{"l_shipmode" : "AIR"}';
                             QUERY PLAN
--------------------------------------------------------------------
 Seq Scan on products  (cost=0.00..4205822.65 rows=59986 width=252)
   Filter: (order_details @> '{"l_shipmode": "AIR"}'::jsonb)
(2 rows)

JSONB stöder FULL-TEXT-SEARCH Indextypen GIN som hjälper frågor som ovan.
Låt mig skapa ett GIN-index och se om det hjälper

dbt3=# create index od_gin_idx on products using gin(order_details jsonb_path_ops);
CREATE INDEX

Om du kan observera nedan, hämtar frågan GIN-indexet

dbt3=# explain select * from products where order_details @> '{"l_shipmode" : "AIR"}';
                                  QUERY PLAN
-------------------------------------------------------------------------------
 Bitmap Heap Scan on products  (cost=576.89..215803.18 rows=59986 width=252)
   Recheck Cond: (order_details @> '{"l_shipmode": "AIR"}'::jsonb)
   ->  Bitmap Index Scan on od_gin_idx  (cost=0.00..561.90 rows=59986 width=0)
         Index Cond: (order_details @> '{"l_shipmode": "AIR"}'::jsonb)

Och ett B-TREE-index istället för GIN skulle INTE hjälpa

dbt3=# create index idx on products((order_details->>'l_shipmode'));
CREATE INDEX

dbt3=# \d products
                  Table "dbt3.products"
    Column     |  Type  | Collation | Nullable | Default
---------------+--------+-----------+----------+---------
 item_code     | bigint |           | not null |
 order_details | jsonb  |           |          |
Indexes:
    "products_pkey" PRIMARY KEY, btree (item_code)
    "idx" btree ((order_details ->> 'l_shipmode'::text))

Du kan se nedan, frågan föredrar FULL TABLE-SCAN

dbt3=# explain select * from products where order_details @> '{"l_shipmode" : "AIR"}';
                             QUERY PLAN
--------------------------------------------------------------------
 Seq Scan on products  (cost=0.00..4205822.65 rows=59986 width=252)
   Filter: (order_details @> '{"l_shipmode": "AIR"}'::jsonb)

Vad är GIN-index?

GIN står för Generalized Inverted Index. Kärnan i GIN Index är att påskynda fulltextsökningar. När du söker baserat på specifika nycklar eller element i en TEXT eller ett dokument, är GIN Index rätt väg att gå. GIN Index lagrar "Nyckel" (eller ett element eller ett värde) och "positionslista"-paren. Positionslistan är nyckelns rad-ID. Detta innebär att om "nyckeln" förekommer på flera ställen i dokumentet, lagrar GIN-index nyckeln endast en gång tillsammans med dess position för händelser, vilket inte bara håller GIN-indexet kompakt i storlek och också hjälper till att påskynda sökningarna på ett bra sätt. sätt. Detta är förbättringen i Postgres-9.4.

Utmaningar med GIN-index

Beroende på datas komplexitet kan det vara dyrt att upprätthålla GIN-index. Skapandet av GIN-index kräver tid och resurser eftersom Indexet måste söka igenom hela dokumentet för att hitta nycklarna och deras rad-ID. Det kan vara ännu mer utmanande om GIN-indexet är uppsvällt. Storleken på GIN-index kan också vara mycket stor baserat på datastorlek och komplexitet.

Indexering av JSON

JSON stöder inte textsökning och index som GIN

dbt3=# create index pd_gin_idx on product using gin(productdetails jsonb_path_ops);
ERROR:  operator class "jsonb_path_ops" does not accept data type json

Normal indexering som B-TREE stöds av både JSON och JSONB

Ja, normala index som B-TREE Index stöds av både JSON- och JSONB-datatyper och är inte gynnsamma för textsökningsoperationer. Varje JSON-objektnyckel kan indexeras individuellt vilket verkligen skulle hjälpa ENDAST när samma objektnyckel används i WHERE-satsen.
Låt mig skapa ett B-TREE Index på JSONB och se hur det fungerar

dbt3=# create index idx on products((order_details->>'l_shipmode'));
CREATE INDEX

dbt3=# \d products
                  Table "dbt3.products"
    Column     |  Type  | Collation | Nullable | Default
---------------+--------+-----------+----------+---------
 item_code     | bigint |           | not null |
 order_details | jsonb  |           |          |
Indexes:
    "products_pkey" PRIMARY KEY, btree (item_code)
    "idx" btree ((order_details ->> 'l_shipmode'::text))

Vi har redan lärt oss ovan att ett B-TREE-index INTE är användbart för att påskynda SQL-filer som gör FULLTEXTSÖKNING på JSON-data med operatorer (som "@>") , och sådana index skulle ENDAST hjälpa till att snabba upp frågorna som t.ex. den nedan, som är typiska SQL-filer av RDBMS-typ (som inte är sökfrågor). Var och en av JSON-objektnycklarna kan indexeras individuellt, vilket skulle hjälpa frågor att snabba upp när dessa indexerade JSON-objektnycklar används WHERE-satsen.
Exemplet nedan använder frågan "l_shipmode" Object Key i WHERE-satsen och eftersom den är indexerad, frågan går för en indexskanning. Om du vill söka med en annan objektnyckel, så skulle frågan välja att göra en HELT TABELL-SCANNING.

dbt3=# explain select * from products where order_details->>'l_shipmode'='AIR';
                                   QUERY PLAN
---------------------------------------------------------------------------------
 Index Scan using idx on products  (cost=0.56..1158369.34 rows=299930 width=252)
   Index Cond: ((order_details ->> 'l_shipmode'::text) = 'AIR'::text)

Samma fungerar med JSON-datatyp också

dbt3=# create index idx on products((order_details->>'l_shipmode'));
CREATE INDEX

dbt3=# \d products
                  Table "dbt3.products"
    Column     |  Type  | Collation | Nullable | Default
---------------+--------+-----------+----------+---------
 item_code     | bigint |           | not null |
 order_details | json  |           |          |
Indexes:
    "products_pkey" PRIMARY KEY, btree (item_code)
    "idx" btree ((order_details ->> 'l_shipmode'::text))

Om du kan observera använder frågan indexet

dbt3=# explain select * from products where order_details->>'l_shipmode'='AIR';
                                   QUERY PLAN
---------------------------------------------------------------------------------
 Index Scan using idx on products  (cost=0.56..1158369.34 rows=299930 width=252)
   Index Cond: ((order_details ->> 'l_shipmode'::text) = 'AIR'::text)

Slutsats

Här är några saker att komma ihåg när du använder PostgreSQL JSON Data...

  • PostgreSQL är ett av de bästa alternativen för att lagra och bearbeta JSON-data
  • Med alla kraftfulla funktioner kan PostgreSQL vara din dokumentdatabas
  • Jag har sett arkitekturer där två eller flera datalager väljs, med en blandning av PostgreSQL- och NoSQL-databaser som MongoDB eller Couchbase-databas. Ett REST API skulle hjälpa applikationer att skicka data till olika datalager. Med PostgreSQL som stöder JSON kan denna komplexitet i arkitektur undvikas genom att bara välja ett datalager.
  • JSON-data i PostgreSQL kan efterfrågas och indexeras vilket ger otrolig prestanda och skalbarhet
  • JSONB-datatyp är det mest föredragna alternativet eftersom det är bra på lagring och prestanda. Stöder fullt ut FULLTEXTSÖKNING och indexering. Ger bra prestanda
  • Använd endast JSON-datatyp om du vill lagra JSON-strängar som JSON och du inte utför mycket komplexa textsökningar
  • Den största fördelen med att ha JSON i PostgreSQL är att sökningen kan utföras med SQLs
  • JSON-sökprestanda i PostgreSQL har varit i nivå med de bästa NoSQL-databaserna som MongoDB

  1. MySQL med Node.js

  2. MySQL:Hur kopierar man rader, men ändrar några fält?

  3. 2013 MVP Summit:En snabb recension och en titt framåt

  4. Hur åtgärdar jag felet "Named Pipes Provider, error 40 - Kunde inte öppna en anslutning till" SQL Server?