Prosíme přihlašte se nebo zaregistrujte.

Přihlašte se svým uživatelským jménem a heslem.

Novinky: Děkujeme všem návštěvníkům fóra, kteří ochotně radí ostatním. Vaše práce je velmi potřebná a vážíme si jí.

Autor Téma: MySQL a dynamická reference tabulky  (Přečteno 3798 krát)

mka

  • Závislák
  • ****
  • Příspěvků: 1907
  • Karma: +119/-78
  • Chybovat je moje.
    • Zobrazit profil
    • Příložany Cé Zet
MySQL a dynamická reference tabulky
« kdy: 13 Duben 2010, 11:56:56 »
Zdravím,
velice by mi bodla možnost používat v SQL příkazu dynamickou referenci tabulky, tedy např. select * from něco, kde bych to něco mohl definovat opět pomocí nějakého SQL příkazu (funkce) v závislosti (např.) na aktuálním datu.
Nemohu nikde nic najít a obávám se, že to asi ani nejde. Nicméně - nevíte někdo o nějakém způsobu, jak to udělat?
P.S.
Samo, že to mohu obejít tak, že si napíšu skript v php. Ale to je v tomhle případě až poslední volba.

jfoot

  • Člen
  • **
  • Příspěvků: 197
  • Karma: +38/-1
  • ..nemožné ihned, zázraky do tří dnů...
    • Zobrazit profil
Re: MySQL a dynamická reference tabulky
« Odpověď #1 kdy: 13 Duben 2010, 12:05:22 »
Zdravím mka,

možná jsem to nepochopil ,ale mysql by mělo umět na serverové straně prepared statements, řekl bych, že to co hledáte je zde.
Po šesté atomové válce  povrch planety Rogoz nevypadal pěkně...

Dítě nevinné...Co ty můžeš vědět...o sadomasochistické derivaci oidipovského komplexu...(O.Neff, K. Saudek, Arnal & Dva dračí zuby)

mka

  • Závislák
  • ****
  • Příspěvků: 1907
  • Karma: +119/-78
  • Chybovat je moje.
    • Zobrazit profil
    • Příložany Cé Zet
Re: MySQL a dynamická reference tabulky
« Odpověď #2 kdy: 13 Duben 2010, 12:37:08 »
Zdravím mka,

možná jsem to nepochopil ,ale mysql by mělo umět na serverové straně prepared statements, řekl bych, že to co hledáte je zde.

Pěkné, jenže zatímco konstrukce např.
Kód: [Vybrat]
prepare myxsel from "select * from acc_log where ?" funguje, tak konstrukce
Kód: [Vybrat]
prepare myxsel from "select * from ? where 1" už ne.

jfoot

  • Člen
  • **
  • Příspěvků: 197
  • Karma: +38/-1
  • ..nemožné ihned, zázraky do tří dnů...
    • Zobrazit profil
Re: MySQL a dynamická reference tabulky
« Odpověď #3 kdy: 13 Duben 2010, 13:08:47 »
Zdravím mka,

a co tohle :
Kód: [Vybrat]
prepare myxsel from "select * from ? where 1=1"  

btw, to je příklad, který zamezuje tomu, aby  příkaz PREPARE "rupnul", když se do klauzule WHERE  nesestaví žádná podmínka...
« Poslední změna: 13 Duben 2010, 13:16:54 od jfoot »
Po šesté atomové válce  povrch planety Rogoz nevypadal pěkně...

Dítě nevinné...Co ty můžeš vědět...o sadomasochistické derivaci oidipovského komplexu...(O.Neff, K. Saudek, Arnal & Dva dračí zuby)

petergula

  • Závislák
  • ****
  • Příspěvků: 1016
  • Karma: +92/-4
    • Zobrazit profil
Re: MySQL a dynamická reference tabulky
« Odpověď #4 kdy: 13 Duben 2010, 13:48:14 »
Prepare statement nemoze mat parameter v klauzuli from, DTB server by nevedel vobec nic preparovat, ak by parametrom bola tabulka, cize by bol uplne zbytocny preparing.
ntbk Dell 6420 (Amd Ati, Intel i7, 4GB RAM, 256GB SSD ...)
secondary/u svokrovcov:
Xubuntu (64bit) ntbk Asus A6Je (Ati X1450, Intel Core2Duo T5500, 2.5GB RAM ...)

wam]Spider007

  • Host
Re: MySQL a dynamická reference tabulky
« Odpověď #5 kdy: 13 Duben 2010, 13:51:51 »
ale do prepare si vie dat uz konkretne vyskladany string (nejaku premennu typu VARCHAR) a ten moze poskladat niekde predtym a dynamicky tak vkladat rozne tabulky.

nie som teraz pri svojom PC, ale mozem sa na to pozriet vecer, lebo nieco podobne som riesil.


inac je este mozne pouzit proceduru na konci ktorej je select....a jej spustenie sa potom sprava ako tabulka.

napriklad:
Kód: [Vybrat]
CREATE PROCEDURE TEST (IN _HODNOTA INT)
BEGIN

IF _HODNOTA = 1 THEN
SELECT * FROM TABULKA1;
ELSE
SELECT * FROM TABULKA2;
END IF;
END;

ked das potom CALL TEST(1); tak procedura vrati prvy select, takto je mozne dat do procedury XY selectov
« Poslední změna: 13 Duben 2010, 13:58:13 od wam]Spider007 »

mka

  • Závislák
  • ****
  • Příspěvků: 1907
  • Karma: +119/-78
  • Chybovat je moje.
    • Zobrazit profil
    • Příložany Cé Zet
Re: MySQL a dynamická reference tabulky
« Odpověď #6 kdy: 13 Duben 2010, 14:28:46 »
Zdravím mka,

a co tohle :
Kód: [Vybrat]
prepare myxsel from "select * from ? where 1=1"  

btw, to je příklad, který zamezuje tomu, aby  příkaz PREPARE "rupnul", když se do klauzule WHERE  nesestaví žádná podmínka...

Bohužel to, co je v tomhle případě za ? je irelevantní. Řve to "syntax error" už na ?; na místě reference tabulky prostě být nemůže.

mka

  • Závislák
  • ****
  • Příspěvků: 1907
  • Karma: +119/-78
  • Chybovat je moje.
    • Zobrazit profil
    • Příložany Cé Zet
Re: MySQL a dynamická reference tabulky
« Odpověď #7 kdy: 13 Duben 2010, 14:32:37 »
ale do prepare si vie dat uz konkretne vyskladany string (nejaku premennu typu VARCHAR) a ten moze poskladat niekde predtym a dynamicky tak vkladat rozne tabulky.

nie som teraz pri svojom PC, ale mozem sa na to pozriet vecer, lebo nieco podobne som riesil.


inac je este mozne pouzit proceduru na konci ktorej je select....a jej spustenie sa potom sprava ako tabulka.

napriklad:
Kód: [Vybrat]
CREATE PROCEDURE TEST (IN _HODNOTA INT)
BEGIN

IF _HODNOTA = 1 THEN
SELECT * FROM TABULKA1;
ELSE
SELECT * FROM TABULKA2;
END IF;
END;

ked das potom CALL TEST(1); tak procedura vrati prvy select, takto je mozne dat do procedury XY selectov

To by samozřejmě šlo, kdyby výčet tabulek byl dán předem a byl konečný. V daném případě je název tabulky tvořen rokem a měsícem (RRRR_MM), takže ...

jfoot

  • Člen
  • **
  • Příspěvků: 197
  • Karma: +38/-1
  • ..nemožné ihned, zázraky do tří dnů...
    • Zobrazit profil
Re: MySQL a dynamická reference tabulky
« Odpověď #8 kdy: 13 Duben 2010, 15:09:38 »
Zdravím srdečně zde všechny diskutující,

Prepare statement nemoze mat parameter v klauzuli from, DTB server by nevedel vobec nic preparovat, ak by parametrom bola tabulka, cize by bol uplne zbytocny preparing.

Ano, také jsem si to myslel, že to přímo v sql nejde, ale některé db servery to údajně umí (nemám vyzkoušeno).

takže to co navrhuje  wam]Spider007 :
ale do prepare si vie dat uz konkretne vyskladany string (nejaku premennu typu VARCHAR) a ten moze poskladat niekde predtym a dynamicky tak vkladat rozne tabulky.
by mohlo fungovat.
Tady je dotaz na tento problém přímo v prostoru mysql. Já mysql,  moc nepoužívám, a bylo by pro mě překvapením, kdyby přímo v mysql bylo možné deklarovat proměnné a přiřadit jim primitivní typ, jak se tvrdí na konci diskuse tohoto vlákna.  Co není dnes ale může být zítra, že... :D
Dejte vědět, jestli to funguje, rád se poučím.    ;)
« Poslední změna: 13 Duben 2010, 15:13:28 od jfoot »
Po šesté atomové válce  povrch planety Rogoz nevypadal pěkně...

Dítě nevinné...Co ty můžeš vědět...o sadomasochistické derivaci oidipovského komplexu...(O.Neff, K. Saudek, Arnal & Dva dračí zuby)

mka

  • Závislák
  • ****
  • Příspěvků: 1907
  • Karma: +119/-78
  • Chybovat je moje.
    • Zobrazit profil
    • Příložany Cé Zet
Re: MySQL a dynamická reference tabulky
« Odpověď #9 kdy: 13 Duben 2010, 15:49:26 »
No mě to (jak to je uvedeno na koci) tedy nefunguje. Zřejmě proto, že - jak se uvádí před tím -
Citace
Table names, column names, etc. cannot be dynamic in the way you
describe. This is not permitted by the SQL language, for many reasons.

For instance, there would be no way for the query optimizer to decide
which index(es) to use, if it doesn't know at parse time which tables
and columns are being queried.

Find another way to solve your problem.

Takže zřejmě smolík :-)

wam]Spider007

  • Host
Re: MySQL a dynamická reference tabulky
« Odpověď #10 kdy: 13 Duben 2010, 19:24:25 »
no, tak uz som doma a overil som si to :) a funguje to :)

takze postup nasledovny:

vytvoris si premennu, do ktorej si nasackujes nazov tabulky (podla tvojho vzoru RRRR_MM).
napriklad _TABULKA = '2010_04' alebo zavinacova premenna @TABULKA = '2010_04' to je jedno
potom si vytvoris "zavinacovu premennu", do ktorej vlozis constantny string select a zan das nazov tabulky.

-- poznamka, zavinacove premenne nemusis deklarovat
Kód: [Vybrat]
SET @STM = CONCAT('SELECT * FROM ', @TABULKA);
a potom uz len samotny prepare
Kód: [Vybrat]
PREPARE STM1 FROM @STM;
EXECUTE STM1;
DEALLOCATE PREPARE STM1;

funkcnost overena v mojej konzole na mysql verzie 5.1 :)

vid vypis:
Kód: [Vybrat]
mysql> set @tabulka = 'WORK';
Query OK, 0 rows affected (0.00 sec)

mysql> set @stm = concat('SELECT * FROM ', @tabulka);
Query OK, 0 rows affected (0.01 sec)

mysql> prepare STM1 FROM @stm;
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> execute STM1;
+-------+-------+------------+------+---------------------+----------+---------------------+----------+
| MWOID | MCUID | DATUM      | HOUR | CREADATE            | CREAUSER | CHNGDATE            | CHNGUSER |
+-------+-------+------------+------+---------------------+----------+---------------------+----------+
|     1 |     1 | 2009-09-02 | 2.00 | 2009-09-02 22:32:49 | admin    | 2009-09-02 22:32:49 | admin    |
|     3 |     1 | 2009-10-13 | 4.00 | 2009-10-13 23:19:32 | admin    | 2009-10-13 23:19:32 | admin    |
+-------+-------+------------+------+---------------------+----------+---------------------+----------+
2 rows in set (0.05 sec)

mysql> deallocate PREPARE STM1;
Query OK, 0 rows affected (0.00 sec)

ja som to sice pouzil len takto na rychlo v konzole, je ale mozne vytvorit aj proceduru a taktiez v nej mozes vyuzivat premenne so zavinacom.
vid priklad jednej mojej jednoduchsej procedury

Kód: [Vybrat]
CREATE PROCEDURE SARZ_C (IN _MSZID INT, IN _USER VARCHAR(50), IN _PPAL INT, IN _MMHID INT)
BEGIN
DECLARE _TYP CHAR(2);
DECLARE _DATUM DATE;

SELECT TYP, DATUM INTO _TYP, _DATUM FROM MADH WHERE MMHID = _MMHID;

SET @STR = _PPAL;
SET @MSZID = _MSZID;
SET @USERL = _USER;
SET @MMHID = _MMHID;
SET @DATUM = _DATUM;

IF _TYP = 'PR' THEN

WHILE _PPAL > 0 DO
INSERT INTO SARZ (MSZID, DPRJ, MHPRJ, CREADATE, CREAUSER, CHNGDATE, CHNGUSER)
SELECT _MSZID, _DATUM, _MMHID, NOW(), _USER, NOW(), _USER;

SET _PPAL = _PPAL - 1;
END WHILE;

ELSEIF _TYP = 'VY' THEN

SET @STM = 'UPDATE SARZ SET DVYD = ?, CHNGDATE = NOW(), CHNGUSER = ?, MHVYD = ? WHERE DPRJ <= ? AND MSZID = ? AND COALESCE(MHVYD, 0) = 0 LIMIT ?';
PREPARE STMT1 FROM @STM;
EXECUTE STMT1 USING @DATUM, @USERL, @MMHID, @DATUM, @MSZID, @STR;
DEALLOCATE PREPARE STMT1;

END IF;
END;
« Poslední změna: 13 Duben 2010, 19:29:12 od wam]Spider007 »

jfoot

  • Člen
  • **
  • Příspěvků: 197
  • Karma: +38/-1
  • ..nemožné ihned, zázraky do tří dnů...
    • Zobrazit profil
Re: MySQL a dynamická reference tabulky
« Odpověď #11 kdy: 14 Duben 2010, 08:54:05 »
Zdravím ,

mka dík za info,  wam]Spider007 K+ za otestované poučení, ukládám info do zásobárny vědomostí a někdy zjistím, jestli tohle náhodou neumí i Postgresql.
Nikdy mě totiž nenapadlo deklarovat proměnné na úrovni sql, přípravu sql příkazů totiž používám zásadně na úrovni jazyka, do kterého sql příkazy "embeduju", ne na úrovni sql.  Dík Ještě jednou  oběma, pánové.
Po šesté atomové válce  povrch planety Rogoz nevypadal pěkně...

Dítě nevinné...Co ty můžeš vědět...o sadomasochistické derivaci oidipovského komplexu...(O.Neff, K. Saudek, Arnal & Dva dračí zuby)

mka

  • Závislák
  • ****
  • Příspěvků: 1907
  • Karma: +119/-78
  • Chybovat je moje.
    • Zobrazit profil
    • Příložany Cé Zet
Re: MySQL a dynamická reference tabulky
« Odpověď #12 kdy: 14 Duben 2010, 09:26:21 »
Skvělý, Spajdr, skvělý.
Vykoledoval sis K++.
Celý kouzlo spočívá, jak vidno, v obyčejný konstrukci
Kód: [Vybrat]
set @stm = concat('SELECT * FROM ', ...);, tedy v sestavení si příkazu do stringu.
Vřelé díky.