sytuacja:
Chcę utworzyć funkcję mysql o nazwie XMLify, które odbywają się w ciąg znaków i wyrażenia, które zwraca zestawfunkcja MySQL UDF aby powrócić XML
XMLify(string, expr)
Funkcja powinna zawiń każde zwrócone pole każdego zwróconego wiersza w zestawie do własnego znacznika XML. Nazwa tagu powinna być nazwą pola.
Mały przykład:
select XMLify('foo', (SELECT 1 as `a`, 2 as `b` UNION SELECT 3 as `a`, 4 as `b`));
powinien zwrócić:
<foo><a>1</a><b>2</b></foo><foo><a>3</a><b>4</b></foo>
Chcę mieć to, ponieważ umożliwi mi uruchomić kompleksową frazę wiele łączy i/lub podzapytania zależnych, bez konieczności zwracania nadmiarowych danych do klienta.
Mam już obejście bez funkcji, którą chcę zbudować. Ale wymaga to pisania trudnych pytań, które nie są łatwe do utrzymania. Zobacz moje przykłady poniżej.
Upewnienie się, że nazwy pól są poprawne Nazwa węzła XML jest dla późniejszego problemu. Gdy funkcja stanie, pomyślę o jakimś algorytmie, który zajmie nazwę pola i przekształci go w legalną nazwę węzła XML.
Również ucieczka danych XML jest dla późniejszego niepokoju. Zostanie to wykonane przy użyciu innej funkcji o nazwie CDATAify
, która po prostu zapisze wszystkie dane w <![CDATA[
i ]]>
i spowoduje uniknięcie wszelkich wcześniejszych wystąpień ]]>
w danych w .
Nie udało mi się tego dokonać przy użyciu zapisanych funkcji w MySQL, ponieważ te nie biorą w zestawach wyników. Ponadto, nawet jeśli miałbyś przekazać SQL jako ciąg, a następnie przygotować instrukcję i wykonać ją, nie możesz uzyskać dostępu do pól, jeśli jeszcze nie znasz nazw pól.
Więc teraz zastanawiam się, czy sztuczka może zostać wykonana za pomocą funkcji zdefiniowanych przez użytkownika (UDF). To jest coś, z czym jeszcze nie współpracowałem, i chciałbym, żeby pani poradziła tutaj przed zawikłaniem.
PYTANIA:
Więc moje pytania teraz to:
- Podsumowując, chciałbym mieć funkcję MySQL, że mogę przekazać wyrażenie lub wynikowej ustawić i gdzie mogę również użyć nazwy pól zestawu wyników.
- Czy zakładam, że nie będzie to możliwe w przechowywanych funkcjach?
- Czy UDF będzie wykorzystywał expessions/ich zestaw wyników jako argument?
- Czy funkcja UDF zezwala na dostęp do nazw pól zestawu wyników, więc mogę używać ich jako nazw znaczników XML?
- Czy to działa również na Windowsie? Czytałem, że UDF ma pewne ograniczenia.
- Czy istnieje lepszy sposób, o którym jeszcze nie pomyślałem?
- Czy będę w stanie utworzyć plik UDF .dll, który mogę utworzyć na własnym komputerze programistycznym, a następnie skopiować plik .dll na mój serwer i użyć go tam?
- Jak uzyskać ten program na rolce? Proszę być dokładnym i wziąć pod uwagę, że mam 64-bitowy MySQL 5.5 na komputerze z systemem Windows.
PRZYKŁAD:
Wyobraźmy sobie, że przez 3 następujące tabele:
users: grades: toys:
+----+------+ +--------+-------+ +--------+--------------+
| id | name | | userid | grade | | userid | toy |
+----+------+ +--------+-------+ +--------+--------------+
| 1 | Bart | | 1 | E | | 1 | slingshot |
| 2 | Lisa | | 1 | E | | 1 | Krusty |
| .. | ... | | 2 | A | | 2 | Malibu Stacy |
| .. | ... | | 2 | B | | 2 | calculator |
+----+------+ +--------+-------+ +--------+--------------+
My pożądany wynik byłoby ograniczone do Barta i Lisa:
<users>
<user>
<id><![CDATA[1]]></id>
<name><![CDATA[Bart]]></name>
<grades>
<grade><![CDATA[E]]></grade>
<grade><![CDATA[E]]></grade>
</grades>
<toys>
<toy><![CDATA[slingshot]]></toy>
<toy><![CDATA[Krusty]]></toy>
</toys>
</user>
<user>
<id><![CDATA[1]]></id>
<name><![CDATA[Lisa]]></name>
<grades>
<grade><![CDATA[A]]></grade>
<grade><![CDATA[B]]></grade>
</grades>
<toys>
<toy><![CDATA[Malibu Stacey]]></toy>
<toy><![CDATA[calculator]]></toy>
</toys>
</user>
</users>
Rozpatrzenie:
- Nie chcę w PHP lub C#, aby najpierw zapytać o tabelę użytkowników, a następnie dla każdego użytkownika uruchomić dwa dodatkowe zapytania dotyczące ocen i zabawek. Ponieważ dla 1000 użytkowników, byłbym uruchomiony 2001 kwerendy.
- Nie chcę również uruchamiać zapytania ze wszystkimi złączeniami i przechodzić przez zestaw wyników w PHP lub C#, ponieważ nazwa użytkownika byłaby wysyłana tyle razy, ile razy liczba razy razy liczba zabawek. Wyobraź sobie, że masz pole użytkownika zawierające ogromną kroplę!
- Nie mogę po prostu użyć GROUP_CONCAT na połączonych tabelach, ponieważ oceny/zabawki nadal wyglądałyby podwójnie.
- Jeśli użyłbym GROUP_CONCAT z DISTINCT, stracę oceny z tymi samymi, takimi jak dwa Ery Barta.
Obecnie chciałbym użyć poniższej instrukcji, aby uzyskać ten wynik, z udziałem dwóch zależnych podzapytań. Działa to doskonale:
SELECT
CONCAT(
'<users>',
IFNULL(
GROUP_CONCAT(
'<user>',
'<id><![CDATA[',
REPLACE(u.id,']]>',']]]]><![CDATA[>'),
']]></id>',
'<name><![CDATA[',
REPLACE(u.name,']]>',']]]]><![CDATA[>'),
']]></name>',
'<grades>',
(
SELECT
IFNULL(
GROUP_CONCAT(
'<grade><![CDATA[',
REPLACE(g.grade,']]>',']]]]><![CDATA[>'),
']]></grade>'
SEPARATOR ''
),
'')
FROM
grades g
WHERE
g.userid = u.id
),
'</grades>',
'<toys>',
(
SELECT
IFNULL(
GROUP_CONCAT(
'<toys><![CDATA[',
REPLACE(t.toy,']]>',']]]]><![CDATA[>'),
']]></toys>'
SEPARATOR ''
),
'')
FROM
toys t
WHERE
t.userid = u.id
),
'</toys>',
'</user>'
SEPARATOR ''
),
''
),
'</users>'
)
FROM
users u
WHERE
u.name = 'Bart' or u.name = 'Lisa'
;
Teraz, jak można zauważyć, że jest to dość duży i brzydki kwerendy, która rani oczu podczas czytania. Utrzymanie takiego zapytania jest trudne. Jeśli musiałbym Moje funkcje XMLify i CDATAify, może po prostu napisać to zamiast:
SELECT
XMLify('users',(
XMLify('user',(
SELECT
CDATAify(u.id) as id,
CDATAify(u.name) as name,
XMLify('grade',(
SELECT
CDATAify(g.grade) as grade
FROM
grades g
where
g.userid = u.id
)) AS grades,
XMLify('toys',(
SELECT
CDATAify(t.toy) as toy
FROM
toys t
where
t.userid = u.id
)) AS grades
FROM
users u
WHERE
u.name = 'Bart' or u.name = 'Lisa'
))
))
;
EDIT:
Jak wspomniano w komentarzach przez nb, istnieje repository on Github, ewentualnie posiadający wszystko czego potrzebuję. Jednak spędziłem kilka dni, próbując uruchomić to w moim systemie, bez powodzenia. Każda odpowiedź, która zawiera szczegółowe instrukcje instalacji na 64-bitowym serwerze MySQL 5.5 działającym w systemie Windows, jest również akceptowalna.
Proszę wziąć pod uwagę, że nie mam żadnego doświadczenia z markami, plikami makefiles itp. Proszę więc dokładnie wyjaśnić.
Cóż, wydaje się, [będzie to dokładnie to, co chcesz] (https://github.com/mysqludf/lib_mysqludf_xml#readme). To wątpliwe, czy wybrałeś właściwą ścieżkę, widząc, że jedyną rzeczą, której brakuje, są nazwy pól. –
@ N.B. Spędziłem kilka dni, aby to zadziałało, ale ciągle mi się nie udaje. Próbowałem skopiować plik lib_mysqludf_xql.dll, dostarczony w folderze "win" bezpośrednio do mojego serwera MySQL 5.5/lib/plugin i uruchamiając plik installdb.sql, ale nadal otrzymuję komunikat 'ERROR 1126 (HY000): Nie można otworzyć udostępnionego biblioteka 'lib_mysqludf_xql.dll' (errno: 193) '. Chciałem też skompilować własną bibliotekę DLL, ale bez względu na to, co robię, ciągle mi się nie udaje. Próbowałem używać Windows SDK, CMake, Cygwin, ale wydaje się, że po prostu nie wiem jak stworzyć własny .dll. Mam MySQL 5.5 64 bit w systemie Windows, tak jak na moim serwerze. To się nie zmieni.) –
[Sprawdź ten link, sekcja rozwiązywania problemów] (https://github.com/dtrebbien/lib_mysqludf_str/blob/master/README.win_x64.txt) - Nigdy nie używał MySQL w Windows, więc nie mam dużo pomoc tam, ale może być, że albo masz błędną dystrybucję C++ lub MySQL ma inny katalog wtyczek. 'POKAŻ ZMIENNY JAK"% plugin% ";' powinien pokazywać, gdzie próbuje załadować wtyczki. Poza tym, nie wiem, o ile więcej mogę pomóc:/ –