sql >> Database >  >> RDS >> Oracle

Waarom wordt selecteren uit opgeslagen procedure niet ondersteund in relationele databases?

TL;DR :u kunt selecteer uit (tabelwaarde) functies, of uit elke soort functie in PostgreSQL. Maar niet van opgeslagen procedures.

Hier is een "intuïtieve", enigszins database-agnostische verklaring, want ik geloof dat SQL en zijn vele dialecten te veel een organisch gegroeide taal / concept zijn om hier een fundamentele, "wetenschappelijke" verklaring voor te hebben.

Procedures versus functies, historisch gezien

Ik zie niet echt het nut in van het selecteren van opgeslagen procedures, maar ik ben bevooroordeeld door jarenlange ervaring en het accepteren van de status-quo, en ik zie zeker hoe het onderscheid tussen procedures en functies verwarrend kunnen zijn en hoe men zou willen dat ze veelzijdiger en krachtiger zouden zijn. Specifiek in SQL Server, Sybase of MySQL kunnen procedures een willekeurig aantal resultaatsets/updatetellingen retourneren, hoewel dit niet hetzelfde is als een functie die een goed gedefinieerd type retourneert.

Zie procedures als noodzakelijke routines (met bijwerkingen) en van functies als pure routines zonder bijwerkingen. Een SELECT statement zelf is ook "puur" zonder bijwerkingen (afgezien van mogelijke vergrendelingseffecten), dus is het logisch om functies te beschouwen als de enige soorten routines die kunnen worden gebruikt in een SELECT verklaring.

Beschouw functies in feite als routines met sterke gedragsbeperkingen, terwijl procedures willekeurige programma's mogen uitvoeren.

4GL versus 3GL-talen

Een andere manier om dit te bekijken is vanuit het perspectief van SQL als een 4e generatie programmeertaal (4GL) . Een 4GL kan alleen redelijk werken als het zwaar wordt beperkt in wat het kan doen. Gemeenschappelijke tabelexpressies maakten SQL turing-compleet , ja, maar het declaratieve karakter van SQL verhindert nog steeds dat het een taal voor algemene doeleinden is vanuit een praktisch, alledaags perspectief.

Opgeslagen procedures zijn een manier om deze beperking te omzeilen. Soms wil je om compleet te zijn en praktisch. Opgeslagen procedures zijn dus dwingend, hebben bijwerkingen, zijn transactioneel, enz.

Opgeslagen functies zijn een slimme manier om sommige . te introduceren 3GL / procedurele taalfuncties in de zuiverdere 4GL-wereld tegen de prijs van het verbieden van bijwerkingen erin (tenzij je de doos van Pandora wilt openen en volledig onvoorspelbare SELECT hebt verklaringen).

Het feit dat sommige databases toestaan ​​dat hun opgeslagen procedures een willekeurig aantal resultatensets / cursors retourneren, is een kenmerk van hun toestaan ​​van willekeurig gedrag, inclusief bijwerkingen. In principe zou niets van wat ik zei dit specifieke gedrag ook in opgeslagen functies voorkomen, maar het zou erg onpraktisch en moeilijk te beheren zijn als ze dit zouden mogen doen binnen de context van SQL, de 4GL-taal.

Dus:

  • Procedures kunnen procedures, elke functie en SQL aanroepen
  • "Pure" functies kunnen "pure" functies en SQL aanroepen
  • SQL kan "pure" functies en SQL aanroepen

Maar:

  • "Pure" functies die procedures aanroepen, worden "onzuivere" functies (zoals procedures)

En:

  • SQL kan geen procedures aanroepen
  • SQL kan geen "onzuivere" functies aanroepen

Voorbeelden van "pure" tabelwaardefuncties:

Hier zijn enkele voorbeelden van het gebruik van tabelwaardige, "pure" functies:

Oracle

CREATE TYPE numbers AS TABLE OF number(10);
/

CREATE OR REPLACE FUNCTION my_function (a number, b number)
RETURN numbers
IS
BEGIN
    return numbers(a, b);
END my_function;
/

En dan:

SELECT * FROM TABLE (my_function(1, 2))

SQL-server

CREATE FUNCTION my_function(@v1 INTEGER, @v2 INTEGER)
RETURNS @out_table TABLE (
    column_value INTEGER
)
AS
BEGIN
    INSERT @out_table
    VALUES (@v1), (@v2)
    RETURN
END

En dan

SELECT * FROM my_function(1, 2)

PostgreSQL

Ik wil iets zeggen over PostgreSQL.

PostgreSQL is geweldig en dus een uitzondering. Het is ook raar en waarschijnlijk zou 50% van de functies niet in productie moeten worden gebruikt. Het ondersteunt alleen "functies", niet "procedures", maar die functies kunnen als alles fungeren. Bekijk het volgende:

CREATE OR REPLACE FUNCTION wow ()
RETURNS SETOF INT
AS $$
BEGIN
    CREATE TABLE boom (i INT);

    RETURN QUERY
    INSERT INTO boom VALUES (1)
    RETURNING *;
END;
$$ LANGUAGE plpgsql;

Bijwerkingen:

  • Er is een tabel gemaakt
  • Er is een record ingevoegd

Toch:

SELECT * FROM wow();

Opbrengsten

wow
---
1


  1. Volg niet-deterministische MySQL-fouten in Perl

  2. Bepaal of SP-parameter een standaardwaarde heeft in T-SQL

  3. Kan ik dit oplossen met pure mysql? (aansluiten op '' gescheiden waarden in een kolom)

  4. Meerdere INSERTS in één tabel en veel tot veel tafels