Mümkünse bunu yapma.
Cevap bu - bu bir anti-model. Müşteri veriyi istediği tabloyu biliyorsa, o zaman SELECT FROM ThatTable
. Bir veritabanı bunun gerekli olduğu şekilde tasarlanmışsa, alt-optimal olarak tasarlanmış gibi görünmektedir. Bir veri erişim katmanının bir tabloda bir değer olup olmadığını bilmesi gerekiyorsa, bu kodda SQL oluşturmak kolaydır ve bu kodu veritabanına aktarmak iyi değildir.
Bana göre bu, asansörün içine istenen katın numarasını yazabilecek bir cihaz kurmak gibi görünüyor. Git düğmesine basıldıktan sonra, mekanik bir kolu istenen kat için doğru düğmeye hareket ettirir ve basar. Bu, birçok olası sorunu ortaya çıkarır.
Lütfen dikkat: burada alay etme niyeti yok. Aptal asansör örneğim, bu teknikle ilgili sorunları kısa ve öz bir şekilde belirtmek için * hayal edebileceğim en iyi cihazdı *. İşe yaramaz bir yönlendirme katmanı ekler, tablo adı seçimini arayan alanından (sağlam ve iyi anlaşılmış bir DSL, SQL kullanarak) belirsiz / tuhaf sunucu tarafı SQL kodunu kullanarak hibrit bir alana taşır.
Sorgu oluşturma mantığının dinamik SQL'e taşınmasıyla bu tür sorumluluk bölme, kodun anlaşılmasını zorlaştırır. Hata potansiyeli taşıyan özel kod adına standart ve güvenilir bir kuralı (bir SQL sorgusunun neyi seçeceğini nasıl seçtiği) ihlal eder.
İşte bu yaklaşımla ilgili bazı olası sorunların ayrıntılı noktaları:
Dinamik SQL, ön uç kodunda veya yalnızca arka uç kodunda tanınması zor olan SQL enjeksiyonu olasılığını sunar (bunu görmek için bunları birlikte incelemeniz gerekir).
Saklanan prosedürler ve işlevler, SP / işlev sahibinin haklarına sahip olduğu ancak arayanın sahip olmadığı kaynaklara erişebilir. Anladığım kadarıyla, özel bir özen göstermeden, o zaman varsayılan olarak dinamik SQL üreten ve çalıştıran bir kod kullandığınızda, veritabanı dinamik SQL'i çağıranın hakları altında yürütür. Bu, ya ayrıcalıklı nesneleri hiç kullanamayacağınız ya da onları tüm istemcilere açmanız gerektiği anlamına gelir, böylece ayrıcalıklı verilere yönelik potansiyel saldırının yüzey alanını arttırırsınız. Oluşturma zamanında SP / işlevi her zaman belirli bir kullanıcı olarak (SQL Server'da EXECUTE AS
) çalışacak şekilde ayarlamak bu sorunu çözebilir, ancak işleri daha karmaşık hale getirir. Bu, dinamik SQL'i çok cazip bir saldırı vektörü haline getirerek, önceki noktada bahsedilen SQL enjeksiyonu riskini arttırır.
Bir geliştiricinin, onu değiştirmek veya bir hatayı düzeltmek için uygulama kodunun ne yaptığını anlaması gerektiğinde, çalıştırılan tam SQL sorgusunu elde etmeyi çok zor bulacaktır. SQL profil oluşturucu kullanılabilir, ancak bu özel ayrıcalıklar gerektirir ve üretim sistemleri üzerinde olumsuz performans etkilerine neden olabilir. Yürütülen sorgu, SP tarafından günlüğe kaydedilebilir, ancak bu, şüpheli fayda için karmaşıklığı artırır (yeni tabloların yerleştirilmesi, eski verilerin temizlenmesi, vb.) Ve oldukça açık değildir. Aslında, bazı uygulamalar, geliştiricinin veritabanı kimlik bilgilerine sahip olmayacağı şekilde tasarlanmıştır, bu nedenle, gönderilen sorguyu gerçekten görmesi neredeyse imkansız hale gelir.
Var olmayan bir tabloyu seçmeye çalıştığınızda olduğu gibi bir hata oluştuğunda, veritabanından "geçersiz nesne adı" satırları boyunca bir mesaj alırsınız. Bu, SQL'i arka uçta veya veritabanında oluştursanız da tamamen aynı olacaktır, ancak fark şu ki, sistemi gidermeye çalışan bazı zayıf geliştiriciler, bir seviye daha derine, Sorun var, sorunun ne olduğunu anlamaya çalışmak için Her Şeyi Yapan harika prosedürü derinlemesine incelemek. Günlüklerde "GetWidget'te Hata" görünmeyecek, "OneProcedureToRuleThemAllRunner'da Hata" gösterilecektir. Bu soyutlama genellikle bir sistemi daha kötü hale getirecektir .
Bir parametreye dayalı olarak tablo adlarını değiştirmenin sözde C # örneğindeki bir örnek:
string sql = $"SELECT * FROM {EscapeSqlIdentifier(tableName)};"
results = connection.Execute(sql);
Bu, akla gelebilecek her olası sorunu ortadan kaldırmasa da, diğer teknikle ana hatlarıyla belirttiğim kusurlar bu örnekte yok.