sql >> Databasteknik >  >> RDS >> PostgreSQL

Mina favoritpostgreSQL-frågor och varför de är viktiga

Databaser, tabeller, normalisering och en stabil säkerhetskopieringsplan gör att vi kan lagra och underhålla data.

Dessa kombinerade bästa praxis ger oss i sin tur interaktion med dessa data. I dagens datadrivna värld är data värdefullt. Inte bara värdefull, data är ofta avgörande för slutanvändarlösningar som tillhandahålls av produkter och tjänster. Att extrahera insikter, svara på frågor och meningsfulla mätvärden från data med hjälp av frågor och datamanipulation är en integrerad del av SQL i allmänhet.

PostgreSQL är inte annorlunda.

Denna grundläggande krux är avgörande för framgång i alla datadrivna aspekter.

Nedan presenterar jag en kombination av 8 olika frågor eller typer av frågor som jag har funnit intressanta och engagerande att utforska, studera, lära sig eller på annat sätt manipulera datamängder.

De är inte listade i någon ordning av betydelse.

De flesta kommer förmodligen att vara bekanta gamla vänner. Kanske kommer några att bli nya bekantskaper.

Exempeltabeller och data som används är inte lika viktiga som själva konstruktionen av själva frågorna och vad varje fråga returnerar, erbjuder eller tillhandahåller. Många av dem är håna och härledda i demonstrationssyfte och bör inte tas bokstavligt i sina värderingar.

1. Vänster gå med, tänk på eventuella nollor till höger...

Anta att vi i det här exemplet har en löpande rea på två månader och att vi får totalt båda tillsammans.

Ändå, av någon anledning, drog den andra månaden inte på sig och vi vill rikta in oss på vilka dagar som månad ett tog upp läget.

Dessa försäljningar representeras som tabellbetalning och fake_month för denna demonstration.

Att notera:

  • Vi kommer endast att kontrollera om det finns summor som är större än 2000.
  • Vi kommer att begränsa utdata till bara 10 rader.

Till att börja med har vi det här Common Table Expression (CTE) 'genererar ' fake_month-tabellen för oss och frågan som följer.

dvdrental=> WITH fake_month AS(
SELECT setup::date
FROM generate_series('2007-02-01', '2007-02-28', INTERVAL '1 day') AS setup
)
SELECT date_part('day', p.payment_date)::INT AS legit,
SUM(p.amount),
date_part('day', fk.setup)::INT AS fake
FROM payment AS p
LEFT JOIN fake_month AS fk
ON date_part('day', fk.setup)::INT = date_part('day', p.payment_date)::INT
GROUP BY legit, fake
HAVING SUM(p.amount) > 2000
LIMIT 10;
legit | sum | fake
-------+---------+------
1 | 2808.24 | 1
2 | 2550.05 | 2
6 | 2077.14 | 6
8 | 2227.84 | 8
9 | 2067.86 | 9
17 | 3630.33 | 17
18 | 3977.74 | 18
19 | 3908.59 | 19
20 | 3888.98 | 20
21 | 3786.14 | 21
(10 rows)

Ser ut som om båda månaderna bidrog där. Så är detta löst?

Innan vi anser att detta är löst, låt oss besöka ORDER BY-satsen.

Naturligtvis kan du BESTÄLLA MED ASC eller DESC.

Men du kan också BESTÄLLA EFTER NULLER först eller sist och det förändrar saken lite.

Låt oss skriva om den här frågan och använda ORDER BY NULLS först i den legitima kolumnen.

För korthetens skull tar jag bort CTE från utgången, bara vet att den fortfarande finns där och används.

SELECT date_part('day', p.payment_date)::INT AS legit,
SUM(p.amount),
date_part('day', fk.setup)::INT AS fake
FROM payment AS p
LEFT JOIN fake_month AS fk
ON date_part('day', fk.setup)::INT = date_part('day', p.payment_date)::INT
GROUP BY legit, fake
HAVING SUM(p.amount) > 2000
ORDER BY legit NULLS first
LIMIT 10;
legit | sum | fake
-------+---------+------
1 | 2808.24 | 1
2 | 2550.05 | 2
6 | 2077.14 | 6
8 | 2227.84 | 8
9 | 2067.86 | 9
17 | 3630.33 | 17
18 | 3977.74 | 18
19 | 3908.59 | 19
20 | 3888.98 | 20
21 | 3786.14 | 21
(10 rows)

Ingen skillnad alls.

Vad händer om vi BESTÄLLER MED NULLER först på den falska kolumnen? Den till höger sidan av JOIN?

Låt oss se.

SELECT date_part('day', p.payment_date)::INT AS legit,
SUM(p.amount),
date_part('day', fk.setup)::INT AS fake
FROM payment AS p
LEFT JOIN fake_month AS fk
ON date_part('day', fk.setup)::INT = date_part('day', p.payment_date)::INT
GROUP BY legit, fake
HAVING SUM(p.amount) > 2000
ORDER BY fake NULLS first
LIMIT 10;
legit | sum | fake
-------+---------+------
29 | 2717.60 |
30 | 5723.89 |
1 | 2808.24 | 1
2 | 2550.05 | 2
6 | 2077.14 | 6
8 | 2227.84 | 8
9 | 2067.86 | 9
17 | 3630.33 | 17
18 | 3977.74 | 18
19 | 3908.59 | 19
(10 rows)

Nu kommer vi någonstans. Vi kan se för dag 29 och 30 att den falska kolumnen har beställts från toppen av resultatuppsättningen.

På grund av BESTÄLLNING AV falska NULLS först.

Detta löser vår fråga, till vilka dagar "rea 2" slappnat av.

Undrar du...

"Kan vi bara filtrera med WHERE fake IS NULL? "

Så här:

SELECT date_part('day', p.payment_date)::INT AS legit,
SUM(p.amount),
date_part('day', fk.setup)::INT AS fake
FROM payment AS p
LEFT JOIN fake_month AS fk
ON date_part('day', fk.setup)::INT = date_part('day', p.payment_date)::INT
WHERE date_part('day', fk.setup) IS NULL
GROUP BY legit, fake
HAVING SUM(p.amount) > 2000
LIMIT 10;
legit | sum | fake
-------+---------+------
29 | 2717.60 |
30 | 5723.89 |
(2 rows)

Ja det blir bra. Så varför inte bara använda den frågan istället? Varför är det viktigt?

Jag tycker att att använda LEFT JOIN och ORDER BY NULLS först för tabellen på höger sida av JOIN, är ett utmärkt sätt att utforska okända tabeller och datamängder.

Genom att bekräfta vad, om någon, data "saknas ’ på den sidan av sammanfogningsvillkoret först; förbättrar tydlighet och medvetenhet, så att du sedan kan filtrera bort resultaten som ställts in med WHERE IS NULL-satsen, vilket gör det klart.

Naturligtvis kan förtrogenhet med tabellerna och datauppsättningarna potentiellt eliminera behovet av LEFT JOIN som presenteras här.

Det är en värdig fråga för alla som använder PostgreSQL att åtminstone försöka under utforskningen.

2. Strängsammansättning

Sammanfogning, sammanfogning eller tillägg av två strängar, ger ett presentationsalternativ för resultatuppsättningar. Många 'saker ' kan sammanfogas.

Men, som noterats i dokumentationen, accepterar strängsammansättningsoperatorn ('||') icke-stränginmatning, så länge som en är en sträng.

Låt oss se några exempel med frågorna nedan:

postgres=> SELECT 2||' times'||' 2 equals: '|| 2*2;
?column?
---------------------
2 times 2 equals: 4
(1 row)

Vi kan se, siffror och strängar kan alla sättas samman som nämnts ovan.

'||' operatorn är bara en av de som är tillgängliga i PostgreSQL.

Concat()-funktionen accepterar flera argument och sammanfogar dem alla vid retur.

Här är ett exempel på den funktionen i aktion:

postgres=> SELECT concat('Josh ','Otwell') AS first_name;
first_name
-------------
Josh Otwell
(1 row)

Vi kan skicka in fler än två argument om så önskas:

postgres=> SELECT concat('Josh',' ','Otwell') AS first_name;
first_name
-------------
Josh Otwell
(1 row)

Låt oss notera något riktigt snabbt med följande exempel:

postgres=> SELECT CONCAT('Josh',NULL,'Otwell') AS first_name;
first_name
------------
JoshOtwell
(1 row)
postgres=> SELECT 'Josh '||NULL||'Otwell' AS first_name;
first_name
------------
(1 row)
postgres=> SELECT NULL||'Josh '||'Otwell' AS first_name;
first_name
------------
(1 row)
postgres=> SELECT CONCAT(NULL,'Josh','Otwell') AS first_name;
first_name
------------
JoshOtwell
(1 row)

Observera att concat()-funktionen ignorerar NULL oavsett var den placeras i listan med parametrar, medan strängsammansättningsoperatorn inte gör det.

NULL returneras om det finns någonstans i strängen för att sammanfoga.

Var bara medveten om det.

Istället för att manuellt inkludera i strängen som ska sammanfogas, inkluderar PostgreSQL också en concat_ws()-funktion som accepterar en strängseparator som den första parametern.

Vi kommer att besöka den med dessa frågor:

postgres=> SELECT concat_ws('-',333,454,1919) AS cell_num;
cell_num
--------------
333-454-1919
(1 row)
postgres=> SELECT concat_ws(' ','Josh','Otwell') AS first_name;
first_name
-------------
Josh Otwell
(1 row)

concat_ws() accepterar antingen siffror eller strängar som argument och som nämnts ovan, använder det första argumentet som avgränsare.

Hur behandlar concat_ws() NULL?

postgres=> SELECT concat_ws('-',333,NULL,1919) AS cell_num;
cell_num
----------
333-1919
(1 row)
postgres=> SELECT concat_ws(NULL,333,454,1919) AS cell_num;
cell_num
----------
(1 row)

NULL ignoreras om det inte är separatorargumentet som ges till concat_ws().

Då ignoreras alla argument och NULL returneras istället.

Sammanfogning är coolt...

Nu när vi har en uppfattning om hur sammanlänkning fungerar, låt oss titta på ett par exempel på det.

Tillbaka till den skenbara DVD-uthyrningsdatabasen

Anta att vi behöver sammanställa en lista över kunders för- och efternamn, tillsammans med deras e-postadress för att skicka ut ett memo för uppdatering av deras konto.

Jag kommer att begränsa utdata till bara 10 rader för korthetens skull, men ändå visa || operatör.

dvdrental=> SELECT first_name||' '||last_name||'''s email address is: '||email AS name_and_email
FROM customer
LIMIT 10;
name_and_email
--------------------------------------------------------------------------
Jared Ely's email address is: [email protected]
Mary Smith's email address is: [email protected]
Patricia Johnson's email address is: [email protected]
Linda Williams's email address is: [email protected]
Barbara Jones's email address is: [email protected]
Elizabeth Brown's email address is: [email protected]
Jennifer Davis's email address is: [email protected]
Maria Miller's email address is: [email protected]
Susan Wilson's email address is: [email protected]
Margaret Moore's email address is: [email protected]
(10 rows)

Lägg märke till att vi var tvungna att undkomma det enda citatet som användes med apostrof s, genom att använda ytterligare ett enda citat för att visa innehav av e-postadressen för varje kund.

Varför borde du veta det?

Det kan finnas tillfällen då sammanlänkning av data ger dig bättre insikt och förståelse för datamängden du arbetar med. Tillsammans med rapporteringsalternativ kan en sammanlänkning av delade datauppsättningar med andras potentiellt göra dem (data) mer läsbara och lättsmälta.

3. Tillhandahåller IN-värdelista med Subquery's

En underfråga har många kraftfulla användningsområden. Av dessa är det vanligt att tillhandahålla en IN-lista med värden för att kontrollera medlemskap.

Här är en snabb användning.

Anta att vi har kund- och betalningstabeller i en låtsas-dvd-uthyrningsbutik och vill belöna våra fem bästa kunder som hyrde filmer under dagarna 10-13 april.

Föreställ dig att det är en speciell målperiod. Så om kunden spenderade mer än 30 USD vill vi erkänna dem.

Tänk på att det finns andra tillgängliga alternativ för att lösa den här typen av frågor (d.v.s. sammanfogningar, fånga resultat från flera urval, etc...), men underfrågor kan också hantera det.

Vi kommer att börja med hela shebang här. Denna fullständiga fråga returnerar allt vi vill ha för just den här frågan.

dvdrental=> SELECT first_name, last_name, email
FROM customer
WHERE customer_id IN (
SELECT customer_id FROM (
SELECT DISTINCT customer_id, SUM(amount)
FROM payment
WHERE extract(month from payment_date) = 4
AND extract(day from payment_date) BETWEEN 10 AND 13
GROUP BY customer_id
HAVING SUM(amount) > 30
ORDER BY SUM(amount) DESC
LIMIT 5) AS top_five);

Det här exemplet innehåller faktiskt kapslade underfrågor, varav en är en härledd tabell.

Låt oss börja med att borra i den innersta underfrågan, den härledda tabellen.

Den här underfrågan är en helt egen SELECT-sats, som returnerar ett customer_id och en SUM() i kolumnen för belopp.

Endast de kunder som uppfyller kriterierna som kontrolleras av WHERE- och HAVING-klausulerna gör snittet och tunnas ut ytterligare med LIMIT 5;

Varför nästa underfråga du frågar?

Kan vi inte bara använda WHERE customer_id IN-delen av den yttersta SELECT här?

Låt oss se med ett praktiskt tillvägagångssätt.

Jag tar bort AS top_five från underfrågan och provar den yttersta frågan med den nu:

dvdrental=> SELECT first_name, last_name, email
FROM customer
WHERE customer_id IN
(SELECT DISTINCT customer_id, SUM(amount)
FROM payment
WHERE extract(month from payment_date) = 4
AND extract(day from payment_date) BETWEEN 10 AND 13
GROUP BY customer_id
HAVING SUM(amount) > 30
ORDER BY SUM(amount) DESC
LIMIT 5);
ERROR: subquery has too many columns
LINE 3: WHERE customer_id IN (

Här testas IN-medlemskap med endast kolumnen kund_id, men den härledda tabellen returnerar två kolumner och PostgreSQL låter oss veta det.

En lösning är att använda en annan underfråga. Genom att bara välja kund_id från resultatuppsättningen härledda tabeller skapas nästa inre kapslade underfråga.

Nu innehåller IN-predikatet flera rader med en kolumns värden för att kontrollera medlemskap mot WHERE-satsen för customer_id för att göra slutresultaten inställda.

Varför är det viktigt?

Att använda subquerys på detta sätt är kraftfullt på grund av det faktum att antalet värden som potentiellt skulle kunna testas med IN()-predikatet.

Tänk om det fanns 100? Eller mer?

'Hårdkodning ' alla i IN()-listan kan bli problematiska och felbenägna när volymen av värden ökar.

4. generera_series()

Denna uppsättningsreturfunktion är praktisk och superkul att använda och utforska. Jag har använt gener_series() i ovanstående exempel, men det förtjänar ett eget prat. Fokuserar mer på funktionen och kapaciteten.

Jag tycker gener_series() är användbar för jämförande frågor där vissa eller all data saknas.

Eller bara partiell data är tillgänglig när jag utforskar. En praktisk användning är att fylla i tabeller med 'dummy-data '.

Till att börja med skapar vi en enkel tabell:

trial=> CREATE TABLE tbl_1(
trial(> tb_id SERIAL PRIMARY KEY,
trial(> some_day DATE,
trial(> an_amt NUMERIC(4,2));
CREATE TABLE

Använd sedan generera_series() som VÄRDEN för vår INSERT-sats:

trial=> INSERT INTO tbl_1(some_day, an_amt)
VALUES(
generate_series('2018-04-01','2018-04-15',INTERVAL '1 day'),
generate_series(2.43, 34.20, 1.03));
INSERT 0 31

Skapa sedan en andra tabell

trial=> CREATE TABLE tbl_2(
tb2_id SERIAL PRIMARY KEY,
some_day2 DATE,
an_amt2 NUMERIC(4,2));
CREATE TABLE

Fyll också i den med generera_series() i INSERT-satsen:

trial=> INSERT INTO tbl_2(some_day2, an_amt2)
VALUES(
generate_series('2018-05-16','2018-05-31',INTERVAL '1 day'),
generate_series(15.43, 31., 1.03));
INSERT 0 16

Varför är det viktigt?

För att upprepa, gener_series() är så användbar för att skapa låtsas- eller övningsdata.

Jag har funnit att efterliknande av månads- eller dagintervall för jämförelse är exceptionellt med gener_series(). Se avsnitt 1 och CTE där, visar denna användning.

Att skapa en uppsättning kompletta data med gener_series() och använda för att jämföra med lagrad data för att avgöra om någon data saknas har också ett stort värde.

5. Frågan har COUNT() Aggregeringsfunktionen.

Denna enkla, men effektiva aggregatfunktion borde finnas i någons arsenal. Speciellt när man utforskar tabeller eller datauppsättningar för första gången.

Jag menar, vill du verkligen 'VÄLJA allt ' från en tabell med 1 miljon rader?

Bestäm med COUNT(*) hur många poster som finns innan du laddar upp.

Låt oss ta reda på hur många rader filmbordet har i denna skenbara DVD-uthyrningstabell:

dvdrental=> SELECT COUNT(*)
dvdrental-> FROM film;
count
-------
1000
(1 row)

Även om det inte är lika omfattande som över 1 miljon rader, är jag säker på att du ser nyttan.

För att returnera antalet specifika rader kan COUNT(*) filtreras med en WHERE-sats.

Låt oss se hur många filmer som har betyget "G":

dvdrental=> SELECT COUNT(*)
dvdrental-> FROM film
dvdrental-> WHERE rating = 'G';
count
-------
178
(1 row)

Det finns en annan form av COUNT() att vara medveten om. ANTAL(något_uttryck) .

Skillnaderna mellan dem är:

  • COUNT(*) returnerar summan av alla inmatningsrader (inklusive NULLS och dubbletter).
  • ANTAL(något_uttryck ) räknar antalet rader som inte är NULL.

När det används i kombination med nyckelordet DISTINCT, kommer COUNT() att eliminera dubbla poster och endast returnera unika värden.

Låt oss se det i aktion genom att använda COUNT() med DISTINCT för att avgöra hur många unika typer av betyg som finns:

dvdrental=> SELECT COUNT(DISTINCT rating) FROM film;
count
-------
5
(1 row)

Med den här frågan vet vi att det finns 5 typer av betyg.

Varför är det viktigt?

Beroende på vad som spåras eller riktas mot kan det vara viktigt att veta hur många av något som finns. Använd därför COUNT(*) eller COUNT(något_uttryck ) hjälper till med den här typen av utmaningar.

Kom bara ihåg att COUNT(*) inte ignorerar NULL. Alla rader, inklusive dubbletter och NULL-värden, returneras som en del av det slutliga numret.

6. UPPDATERA flera rader med ett CASE-uttryck.

Anta att vi har den här tabellen:

trial=> SELECT * FROM reward_members;
rm_id | expense_amt | member_status
-------+-------------+---------------
1 | 1245.33 | gold
2 | 1300.49 | gold
3 | 900.20 | bronze
4 | 2534.44 | platinum
5 | 600.19 | bronze
6 | 1001.55 | silver
7 | 1097.99 | silver
8 | 3033.33 | platinum
(8 rows)

Vi måste byta namn på kolumnen member_status och lägga till 'grupp ' till slutet av det aktuella namnet som finns för varje post.

Till att börja med kommer flera individuella UPDATE-satser att göra detta utan problem.

Men det kan också ett enda CASE-uttryck.

trial=> UPDATE reward_members
SET member_status = (
CASE member_status
WHEN 'gold' THEN 'gold_group'
WHEN 'bronze' THEN 'bronze_group'
WHEN 'platinum' THEN 'platinum_group'
WHEN 'silver' THEN 'silver_group'
END
)
WHERE member_status IN ('gold', 'bronze','platinum', 'silver');
UPDATE 8

Låt oss fråga tabellen igen för att se ändringarna:

trial=> SELECT * FROM reward_members;
rm_id | expense_amt | member_status
-------+-------------+----------------
1 | 1245.33 | gold_group
2 | 1300.49 | gold_group
3 | 900.20 | bronze_group
4 | 2534.44 | platinum_group
5 | 600.19 | bronze_group
6 | 1001.55 | silver_group
7 | 1097.99 | silver_group
8 | 3033.33 | platinum_group
(8 rows)

Alla uppdateringar lyckades.

Varför är det viktigt?

Du kan föreställa dig hur många tur och retur detta skulle ta till servern om flera individuella UPDATE-satser hade körts. I sanning bara 4 för detta exempel. Men potentialen för många finns alltid där.

Men med en UPPDATERING med CASE-uttryck skickar vi bara en fråga istället.

7. COPY och \copy

PostgreSQL tillhandahåller COPY, ett kommando för att exportera data mellan filer och tabeller.

Var säker och besök den medföljande länken för att se det rikliga antalet alternativ som finns tillgängliga med COPY.

En viktig anmärkning angående COPY. SUPERUSER rollbehörighet krävs för att utföra detta kommando.

psql-metakommandot \copy är ett alternativ för de användare som inte anses vara detta rollattribut. Vi kommer att besöka det kommandot i tur och ordning inom kort.

Låt oss först köra ett COPY-kommando för att exportera vissa kolumner till en CSV-fil på den lokala datorn.

Anta att vi har det här frågeresultatet till för export:

trial=# SELECT expense_amt, member_status
trial-# FROM reward_members
trial-# WHERE member_status = 'gold_group';
expense_amt | member_status
-------------+---------------
1245.33 | gold_group
1300.49 | gold_group
(2 rows)

Med COPY kan vi använda den SELECT-satsen för att slutföra denna export.

trial=# COPY (SELECT expense_amt, member_status
FROM reward_members
WHERE member_status = 'gold_group')
TO '/home/linux_user_here/awards_to_honor.csv'
DELIMITER ','
CSV HEADER;
COPY 2

*Obs:Enligt dokumentationen måste frågan vara inom parentes.

Låt oss nu kontrollera innehållet i den filen:

$ cat awards_to_honor.csv
expense_amt,member_status
1245.33,gold_group
1300.49,gold_group

Vi kan se att den första raden innehåller HEADER (som är kolumnnamnen) och båda raderna har kostnads_amt- och medlemsstatusdata för båda kolumnerna som returneras från WHERE-satsfiltret.

En annan viktig varning upptäckte jag när jag körde ovanstående COPY-kommando.

Användaren måste ha behörighet att skriva till filen på OS-nivå.

I mitt fall, fixat med:

$ sudo chown postgres awards_to_honor.csv

Du kan undvika det här problemet genom att istället skriva till en systemfil som den aktuella användaren har tillgång till såsom /tmp (visas nedan.)

trial=# COPY (SELECT expense_amt, member_status
FROM reward_members
WHERE member_status = 'gold_group')
TO '/tmp/awards_to_honor.csv'
DELIMITER ','
CSV HEADER;
COPY 2

En av mina testroller utan SUPERUSER-attributet stötte dock på problem med att skriva till /tmp-filen.

Se nedan för bekräftelse:

trial=# SET role log_user; -- changing from postgres user to log_user
SET

Försöker nu samma COPY-kommando, skriver till /tmp-mappen

trial=> COPY (SELECT expense_amt, member_status
FROM reward_members
WHERE member_status = 'gold_group')
TO '/tmp/awards_to_honor2.csv'
DELIMITER ','
CSV HEADER;
ERROR: must be superuser to COPY to or from a file
HINT: Anyone can COPY to stdout or from stdin. psql's \copy command also works for anyone.

Kanske ett bättre mått, som föreslås i TIPS:, för roller utan attributet SUPERUSER, är metakommandot psql \copy.

Låt oss utföra en liknande typ av kommando med \copy istället med samma roll, utan att behöva det SUPERUSER-attributet.

trial=> \copy (SELECT expense_amt, member_status
FROM reward_members
WHERE member_status = 'silver_group')
TO '/home/linux_user_here/more_awards.csv'
DELIMITER ','
CSV HEADER;
COPY 2

Inga problem där.

Och filernas innehåll,

$ cat more_awards.csv
expense_amt,member_status
1001.55,silver_group
1097.99,silver_group

Fungerar även för mappen /tmp:

trial=> \copy (SELECT expense_amt, member_status
FROM reward_members
WHERE member_status = 'silver_group')
TO '/tmp/more_awards.csv'
DELIMITER ','
CSV HEADER;
COPY 2

Samma innehåll finns också i den skrivna filen:

trial=> \! cat /tmp/more_awards.csv
expense_amt,member_status
1001.55,silver_group
1097.99,silver_group

Varför är det viktigt?

Att importera data till PostgreSQL via filer är en säker massuppladdningsmetod. Även om alla inte tas upp i det här blogginlägget, erbjuder COPY och \copy båda flera alternativ för att arbeta med olika filformat och filtillägg.

På samma sätt kan export av data från tabeller eller specifika kolumner enkelt hanteras med båda dessa kommandon också.

8. psql \help-metakommando

Du befinner dig i en psql kommandoradssession. Nyfiken på CREATE INDEX kommandosyntax?

Inget behov och gå till en webbläsare eller ett annat dokument.

Prova detta istället:

trial=> \help CREATE INDEX
Command: CREATE INDEX
Description: define a new index
Syntax:
CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON table_name [ USING method ]
( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
[ WITH ( storage_parameter = value [, ... ] ) ]
[ TABLESPACE tablespace_name ]
[ WHERE predicate ]

För att veta vilken hjälptext som är tillgänglig kan du köra \help själv och få en lista över tillgängliga alternativ.

Jag kommer inte att lista dem alla här, bara vet att det alternativet är tillgängligt.

Varför är det viktigt?

Det faktum att detta metakommando är superlätt att använda, kraftfullt och bekvämt är tillräckligt för att nämna det här. Det har sparat mig massor av tid på att leta i annan dokumentation. Och självklart, eftersom jag är nybörjare använder jag den ganska ofta!

Slutsats

Detta är inte en uttömmande lista. Inte heller 'be all end all ' av frågor och datamanipulation.

Endast min syn på de som väcker mitt intresse och talar till mig när jag fortsätter att lära mig och växa till en SQL-utvecklarroll. Jag hoppas att du genom det här blogginlägget kommer att hitta användningsfall för ovanstående frågor och kommandon, och implementera dem där du tycker är lämpligt.


  1. vad är @JoinColumn och hur det används i Hibernate

  2. Är GUID-kollisioner möjliga?

  3. MySQL REPLACE() – Ersätt alla instanser av en delsträng med en annan sträng

  4. Inaktivera PostgreSQL-kontroller av främmande nyckel för migrering