Tek tek SQL deyimleri içine birden fazla SQL ifadeleri bölmek

9 Cevap php

Intro not: Ben bir kütüphane ya da rutin bunu yapmak için var umuyorum, ama bu böyle bir şey bulmak mümkün olmamıştır. Gerçekten yönü ve nereden başlayacağınızı tavsiye arıyorum ...

Here is the situation: I have a block of SQL commands coming as plain text. It might be one SQL commands or several. I need a way to split multiple SQL commands so I can run them one at a time. Microsoft SQL Management Studio does has this behavior out of box.

Apache (Debian) üzerinde çalışan bir uygulama PHP5/MySQL5 bu işlevselliği eklemek için çalışıyorum.

Bazı önemli noktalar:

  1. Ben gerçekten teker teker çalıştırmak gerekiyor. Cidden.
  2. Ben her SQL ifadesinden sonra bir virgül girmek için kullanıcı gerektirmeyen istemiyorum.
  3. SQL ifadeleri bir veya birden fazla satır olabilir, bu yüzden Liderler / CR üzerinde kaydırma olamaz
  4. Bu, SELECT, UPDATE, INSERT destek azından SİL gerekiyor.
  5. Bu alt seçer vardır sorguları desteklemesi gerekiyor
  6. Düzgünce sekmeli SQL çalışmak gerekiyor
  7. (Kullanılabilir yazılım çıkarına) Ben sınırlayıcı her türlü girmek için kullanıcı zorlamak istemiyorum.

Burada iki tablolara bölmek gerekir SQL bir örnek blok:

select sMessage, 
(
    SELECT COUNT(sTag) FROM Tags WHERE ixTicket = note.ixTicket
) FROM note
select * from ticket
    WHERE (SELECT MAX(nCount) FROM Counter WHERE ixTicket = ticket.ixTicket) > 5

Bazı RegEx girişimleri çalıştı, ama o kadar güçlü görünmüyor.

Bu sorunu çözmek için bir yaklaşım üzerinde herhangi bir öneri?

9 Cevap

Ben bu hiç mümkün olduğundan emin değilim. Kesinlikle hedef DBMS SQL sözdizimi derinlemesine bir bilgi gerekir. Sadece kafamın üst kapalı Örneğin bu bir tek MySQL ifadedir:

INSERT INTO things
SELECT * FROM otherthings ON DUPLICATE KEY
UPDATE thingness=thingness+1

Bu, bir sınırlayıcı olmadan, belirsiz olabilir bazı veritabanlarinin yapıları vardır muhtemeldir.

Ben her SQL ifadesinden sonra bir virgül girmek için kullanıcı gerektirmeyen istemiyorum.

Seni zorunda olabilir düşünüyorum. Bu tamamen SQL deyimleri sınırlandırmak için standart bir yol var. Algılamak için bir sezgisel bulabilirsiniz bile muhtemelen-start-of-SQL deyimi noktaları, sen-olmadan-NEREDE-fıkra "şeyler DELETE" bir kaza gibi afetler risk.

SQL ifadeleri bir veya birden fazla satır olabilir, bu yüzden Liderler / CR üzerinde kaydırma olamaz

Çift satır-için-yeni-deyim kabul olurdu?

Bazı RegEx girişimleri çalıştı, ama o kadar güçlü görünmüyor.

Hayır, hatta with noktalı virgül ayraçlar, regex SQL ayrıştırmak için yeterince güçlü yaklaşamaz. Sorun noktaları içerir:

';'
";"
`;`
'\';'
''';'
-- ;
#;
/*;*/

ve bu yapıların bir araya girme. Eek!

Belki bu kütüphane deneyin. Ben geçmişte sql ayrıştırma başarıyla kullanmıştır. http://www.sqlparser.com/

Periyodik sorunları neden tartışma bir cilvesi eklemek için:

DECLARE c CURSOR FOR
    SELECT * FROM SomeWhere ...
        FOR UPDATE

Sondaki GÜNCELLEME kendi adım kapalı ad hoc ayrıştırıcıları atmak eğilimindedir. Biliyorsunuz (gerçekten SQL, değil düz SQL Gömülü) DECLARE notasyonu ilk etapta izin verilmez çünkü bu konuda endişelenmenize gerek yok olabilir. Ama İÇİN UPDATE deyimi SQL bile değilken bir DECLARE açıklamada bazı ağızlarında görünür, yani sakının.

belki şu Java RegExp ile? test edin ...

@Test
public void testRegexp() {
    String s = //
        "SELECT 'hello;world' \n" + //
        "FROM DUAL; \n" + //
        "\n" + //
        "SELECT 'hello;world' \n" + //
        "FROM DUAL; \n" + //
        "\n";

    String regexp = "([^;]*?('.*?')?)*?;\\s*";

    assertEquals("<statement><statement>", s.replaceAll(regexp, "<statement>"));
}

En iyi bahis tabloları arasındaki deliminator çeşit koymak için kullanıcı gerektiren etmektir. Örneğin: Her deyim yalnızca kelime GO, ya da bir "\" içeren bir çizgi ile çizilecektir gerektiren veya her açıklama sonuna ";".

Bu şekilde kolayca ayrı bir SQL deyimleri içine tek dize zarar verebilir.

Eğer kullanıcılar gibi sınırlandırıcı bir karakter koymak istemiyorsanız ';' ya da başka herhangi bir şey, girdisini kendinizi ayrıştırmak ve deyimleri başlar nerede belirlemek için mantık olması gerekir.

Sizin mantık bariz sorgu başlangıç ​​anahtar kelimeler 'SEÇ', 'update', 'INSERT', 'DELETE' ile uğraşmak ve bir sonraki anahtar kelime (giriş veya son) ileri çalışmak gerekir.

Eğer anahtar kelimeler 'SEÇ', 'update', 'INSERT' ve 'DELETE' ('ve parantez kapatma') açılış sayısını sayma ile birlikte kullanmayı denediniz mi?

Bu önlemek iç içe SELECT ifadeleri belirlemek ve ifadesinin doğru son bulması için izin vermelidir.

Sen virgül ayırıcısını gerektiren gerekir. Teknik olarak, o olmadan bir SQL ifadesi tamamen geçersiz; Bunu ihmal herkes biçimlendirilmiş SQL yazıyor. Noktalı virgül gerektiren bir standart biçimde, tüm sorunları çözer, ve yazmak için yazılım kolaylaştırır.

Belki aşağıdakileri yapın: kullanıcı not (tabii tırnak dışında) bir veya daha fazla noktalı virgül içeren bir sorgu girerse, sonunda bir noktalı virgül eklemeniz ve tek sorgu olarak çalıştırın. Aksi takdirde, noktalı virgül de girilen sorguları bölünmüş ve her biri ayrı ayrı çalıştırmak, ihmal varsa belki de son sorgunun sonunda bir noktalı virgül teyel.

Bu çözüm, SQL standardı ile uyumlu, ve sadece düz eserler yazmak kolaydır. Sınırlayıcı gerektirmeyen çılgınlığa emin bir yoldur.

Sen herhalde kendiniz ayrıştırmak. UPDATE, INSERT, EXEC, vb, DELETE, SELECT anahtar kelimeler aramak

Nest_level + +: Eğer bir "(" Bir sayacı artırmak karşılaşırsanız eğer, ayrıştırmak gibi

Eğer bir ")" eksiltme nest_level karşılaşırsanız -

Eğer bir anahtar kelime ve nest_level == 0 rastlamak o zaman, o zaman bir sonraki açıklamaya geldim.

Ayrıca gibi durumlarda ele almak gerekecek

 INSERT ...
 SELECT ....

Yani bir INSERT SELECT veya DEĞERLERE biri için bakmak gerekir ...

Ve şüphesiz diğer durumlarda.

Sadece virgül gerektirir gerekir kquinn katılıyorum. Ben bu konuda "cool" bir şey olduğunu sanmıyorum.