PostgreSQL find locks including the table name - relational-database

I'm trying to take a look at locks that are happening on
specific tables in my PostgreSQL database.
I see there's a table called pg_locks
select * from pg_locks;
Which seems to give me a bunch of columns but is it possible
to find the relation because I see one of the columns is
the relation oid.
What table must I link that to to get the relation name?

This is Remy's query, adjusted for Postgres 10:
select nspname, relname, l.*
from pg_locks l
join pg_class c on (relation = c.oid)
join pg_namespace nsp on (c.relnamespace = nsp.oid)
where pid in (select pid
from pg_stat_activity
where datname = current_database()
and query != current_query());

If you just want the contents of pg_locks but with a human-friendly relation name,
select relation::regclass, * from pg_locks;

Try this :
select nspname,relname,l.* from pg_locks l join pg_class c on
(relation=c.oid) join pg_namespace nsp on (c.relnamespace=nsp.oid) where
pid in (select procpid from pg_stat_activity where
datname=current_database() and current_query!=current_query())

Remy Baron's answer is correct I just wanted to post one I came up
with as well only because it's more specific to what I need in this case
select pg_class.relname,
pg_locks.mode
from pg_class,
pg_locks
where pg_class.oid = pg_locks.relation
and pg_class.relnamespace >= 2200
;

The below command will give the list of locks:
select t.relname,l.locktype,page,virtualtransaction,pid,mode,granted
from pg_locks l, pg_stat_all_tables t where l.relation=t.relid
order by relation asc;

Related

Calculate between two statements

I got two statements and I want to calculate their values. Both values have to be calculated 5 - 5 = ( I want to see the answer 0 )
SELECT COUNT(*) AS 'Aantal stoelen geboekt'
FROM Boekingsregel, Vlucht
WHERE Boekingsregel.Vlucht_Vlucht_Id = Vlucht.Vlucht_Id
AND Vlucht_Datum = '2017-04-10';
SELECT min(Vliegtuig_Aantal_Stoelen) AS 'Max aantal stoelen'
FROM Vliegtuig;
While I do not see any relation of the two queries you also should not use an alias with spaces. Make your alias as short as possible but can define what value it holds, but since this is your query you know better than I do.
As for your problem you can combine the two queries into one something like this:
SELECT BR.`Aantal stoelen geboekt` - VT.`Max aantal stoelen` AS TheResult
FROM (SELECT COUNT(*) AS `Aantal stoelen geboekt`
FROM Boekingsregel, Vlucht
WHERE Boekingsregel.Vlucht_Vlucht_Id = Vlucht.Vlucht_Id
AND Vlucht_Datum = '2017-04-10') BR,
(SELECT min(Vliegtuig_Aantal_Stoelen) AS `Max aantal stoelen` FROM Vliegtuig) VT;
NOTE: Not tested I just type it here.
If this is not what you are looking for then maybe you should explain your requirements in greater detail so dhat everyone can understand and will be able to help you.
First, learn to use proper JOIN syntax.
Second, combine these in the FROM clause.
SELECT COUNT(*) AS AantalStoelenGeboekt, vt.MaxAantalStoelen
FROM Boekingsregel b JOIN
Vlucht v
ON b.Vlucht_Vlucht_Id = v.Vlucht_Id CROSS JOIN
(SELECT min(Vliegtuig_Aantal_Stoelen) AS MaxAantalStoelen
FROM Vliegtuig
) vt
WHERE v.Vlucht_Datum = '2017-04-10';
Note: MySQL allows this syntax. Perhaps a cleaner way is to use an aggregation function on MaxAantalStoelen:
SELECT COUNT(*) AS AantalStoelenGeboekt,
MAX(vt.MaxAantalStoelen) as MaxAantalStoelen
FROM Boekingsregel b JOIN
Vlucht v
ON b.Vlucht_Vlucht_Id = v.Vlucht_Id CROSS JOIN
(SELECT min(Vliegtuig_Aantal_Stoelen) AS MaxAantalStoelen
FROM Vliegtuig
) vt
WHERE v.Vlucht_Datum = '2017-04-10';

MySQL View Creation

I have two tables:
parking_lot
id
name
parking_spot
id
parking_lot_id
available
I would like to create a view that looks like this:
parking_lot_view
id
name
num_spots_available
What would the query to create this view be for a MySQL DB?
If you need to create a view, first start by creating a Select SQL Statement joining whatever tables you need. Then you just add "CREATE VIEW AS" at the beginning and Execute.
In your specific case, this should do the trick (I assumed 'available' is an Integer that contains 0 for unavailable and 1 for available, since you do not specify that in your question):
CREATE VIEW parking_lot_view AS
select L.id, L.name, count(*) available_spots
from parking_lot L inner join parking_spot S on S.parking_lot_id = L.id
where S.available <> 0
group by L.id, L.name
This is a simple query, so I assume you are pretty new to MySQL and databases. You should definitely try to understand how this works and study up on the subject:
create view parking_lot_view as
select pl.id, pl.name, sum(available) as NumAvailable
from parking_spot ps join
parking_lot pl
on ps.parking_lot_id = pl.id
group by pl.id, pl.name;
This assumes that available is 1 when available and 0 otherwise.

NOT EXISTS Clause

I have a Table called "contas" and another table called "cartoes" I need to verify what "IDCARTAO" doesn't exists in table contas, like that: "If I have one conta with cartoes.IDCARTAO = 1, the result needs to be 2 and 3";
SELECT cartoes.IDCARTAO
from cartoes
WHERE NOT EXISTS(SELECT *
from cartoes
LEFT OUTER JOIN contas ON (cartoes.IDCARTAO = contas.IDCARTAO)
WHERE contas.IDCARTAO = cartoes.IDCARTAO)
Why this sql code doesn't work?
Are you looking for this?
SELECT IDCARTAO
FROM cartoes c
WHERE NOT EXISTS
(
SELECT *
FROM contas
WHERE IDCARTAO = c.IDCARTAO
)
Tiny tweak: Instead of using not exists, try not in. As in...
SELECT ct.IDCARTAO
from cartoes ct
WHERE ct.idcartao not in
(SELECT c.idcartao from contas c)
I don't think that's how it works.
In your case, that query would return all records from the cartoes table where there are no records in the cartas table for the given IDCARTAO.
You already have 3 options up there, If you want to filter records with some specific IDCARTAO(means if you have a static list of IDCARTAO), use in. Otherwise I would use the answer from #peterm, because it would be faster when the subquery results is large.
for more reference, please hit EXISTS Condition

Correlated Subquery in a MySQL CASE Statement

Here is a brief explanation of what I'm trying to accomplish; my query follows below.
There are 4 tables and 1 view which are relevant for this particular query (sorry the names look messy, but they follow a strict convention that would make sense if you saw the full list):
Performances may have many Performers, and those associations are stored in PPerformer. Fans can have favorites, which are stored in Favorite_Performer. The _UpcomingPerformances view contains all the information needed to display a user-friendly list of upcoming performances.
My goal is to select all the data from _UpcomingPerformances, then include one additional column that specifies whether the given Performance has a Performer which the Fan added as their favorite. This involves selecting the list of Performers associated with the Performance, and also the list of Performers who are in Favorite_Performer for that Fan, and intersecting the two arrays to determine if anything is in common.
When I execute the below query, I get the error #1054 - Unknown column 'up.pID' in 'where clause'. I suspect it's somehow related to a misuse of Correlated Subqueries but as far as I can tell what I'm doing should work. It works when I replace up.pID (in the WHERE clause of t2) with a hard-coded number, and yes, pID is an existing column of _UpcomingPerformances.
Thanks for any help you can provide.
SELECT
up.*,
CASE
WHEN EXISTS (
SELECT * FROM (
SELECT RID FROM Favorite_Performer
WHERE FanID = 107
) t1
INNER JOIN
(
SELECT r.ID as RID
FROM PPerformer pr
JOIN Performer r ON r.ID = pr.Performer_ID
WHERE pr.Performance_ID = up.pID
) t2
ON t1.RID = t2.RID
)
THEN "yes"
ELSE "no"
END as pText
FROM
_UpcomingPerformances up
The problem is scope related. The nested Selects make the up table invisible inside the internal select. Try this:
SELECT
up.*,
CASE
WHEN EXISTS (
SELECT *
FROM Favorite_Performer fp
JOIN Performer r ON fp.RID = r.ID
JOIN PPerformer pr ON r.ID = pr.Performer_ID
WHERE fp.FanID = 107
AND pr.Performance_ID = up.pID
)
THEN 'yes'
ELSE 'no'
END as pText
FROM
_UpcomingPerformances up

Tricky SQL including outer join and case

I use data from http://geonames.org. The table structure is as follows:
GN_Name 1 - 0:N GN_AlternateName
They are linked on:
(PK)GN_Name.GeoNameId == (FK)GN_AlternateName.GeoNameId
GN_Name is the main table containing all place names.
GN_AlternateName contains names in other languages if any.
EX:
GN_Name.Name - Stockholm
GN_AlternateName.AlternateName - Estocolmo (if IsoLanguage=="es")
Rules:
I want to use GN_AlternateName.AlternateName if it exists for the specified language and if it starts with the search string.
If not, i want to use GN_Name.Name if it starts with the search string.
I want GeoNameId to be unique.
Basically I could outer join in first record only, but that seemed to decrease performance.
I've got the following SQL (basically modified SQL from a LINQ query). The problem is that it only finds 'Estocolmo' if search string starts with "stock". "estoc" yields nothing.
select
distinct(n.GeoNameId) as Id,
an.IsoLanguage,
CASE WHEN (an.AlternateName like N'estoc%')
THEN an.AlternateName
ELSE n.Name
END AS [The name we are going to use]
from GN_Name as n
LEFT OUTER JOIN GN_AlternateName as an
ON n.GeoNameId = an.GeoNameId
AND 'es' = an.IsoLanguage
WHERE n.Name like N'estoc%'
UPDATE
Thanks Rahul and Lee D.
I now have the following:
select
distinct(n.GeoNameId) as Id,
an.IsoLanguage,
CASE WHEN (an.AlternateName like N'estoc%')
THEN an.AlternateName
ELSE n.Name
END AS [The final name]
from GN_Name as n
LEFT OUTER JOIN GN_AlternateName as an
ON n.GeoNameId = an.GeoNameId
AND 'es' = an.IsoLanguage
WHERE (n.Name LIKE N'estoc%' OR an.AlternateName LIKE N'estoc%')
This performs LIKE twice on an.AlternateName. Is there any way i could get rid of on LIKE clause?
UPDATE 2
Andriy M made a nice alternative query using COALESCE. I changed it a little bit and ended up with the following:
SELECT Id, LocalisedName
FROM (
SELECT
n.GeoNameId AS Id,
an.IsoLanguage,
COALESCE(an.AlternateName, n.Name) AS LocalisedName
FROM n
LEFT JOIN GN_AlternateName AS an ON n.GeoNameId = an.GeoNameId
AND IsoLanguage = 'es'
) x
WHERE LocalisedName LIKE 'estoc%'
This query does exactly what i am looking for. Thanks!
Here's a probable solution of the problem, which uses a slightly different apporach:
SELECT Id, LocalisedName
FROM (
SELECT
n.GeoNameId AS Id,
an.IsoLanguage,
COALESCE(an.AlternateName, n.Name) AS LocalisedName
FROM GN_Name AS n
LEFT JOIN GN_AlternateName AS an ON n.GeoNameId = an.GeoNameId
AND IsoLanguage = 'es'
) x
WHERE LocalisedName LIKE 'estoc%'
(Changed it based on your update.)
If I understand correctly, in your example the value 'Estocolmo' is in the GN_AlternateName.AlternateName column, so would be filtered out by the where clause which only looks at GN_Name.Name. What if you change the last line of SQL to:
WHERE n.Name LIKE N'estoc%' OR an.AlternateName LIKE N'estoc%'
I'm assuming 'estoc%' is your search string.
I guess you need to modify the WHERE clause to check in GN_AlternateName table as well
WHERE n.Name like N'estoc%' OR an.AlternateName like 'N'estoc%'