Aracılığıyla paylaş


useFmtOnly kullanılarak ParameterMetaData alınıyor

JDBC sürücüsünü indirin

SQL Server için Microsoft JDBC Sürücüsü, sunucudan Parametre Meta Verilerini sorgulamak için alternatif bir yol içerir; useFmtOnly. Bu özellik ilk olarak sürücünün 7.4 sürümünde kullanıma sunulmuştur ve içindeki sp_describe_undeclared_parametersbilinen sorunlar için geçici bir çözüm olarak gereklidir.

Sürücü öncelikle Parametre Meta Verilerini sorgulamak için saklı yordamı sp_describe_undeclared_parameters kullanır. Bu yordam, çoğu durumda Parametre Meta Verileri alma için önerilen yaklaşımdır. Ancak saklı yordamı yürütmek şu anda aşağıdaki kullanım örnekleri altında başarısız oluyor:

  • Always Encrypted sütunlarına karşı
  • Geçici tablolara ve tablo değişkenlerine karşı
  • Görüşlere karşı

Bu kullanım durumları için önerilen çözüm, kullanıcının SQL sorgusunu parametreler ve tablo hedefleri için ayrıştırmak ve ardından etkin hale getirilmiş sorgusunu yürütmektir. Aşağıdaki kod parçacığı özelliği görselleştirmeye yardımcı olur.

--create a normal table 'Foo' and a temporary table 'Bar'
CREATE TABLE Foo(c1 int);
CREATE TABLE #Bar(c1 int);

EXEC sp_describe_undeclared_parameters N'SELECT * FROM Foo WHERE c1 = @p0' --works fine
EXEC sp_describe_undeclared_parameters N'SELECT * FROM #Bar WHERE c1 = @p0' --fails with "Invalid object name '#Bar'"

SET FMTONLY ON;
SELECT c1 FROM Foo; --works
SET FMTONLY OFF;
SET FMTONLY ON;
SELECT c1 FROM #Bar; --works
SET FMTONLY OFF;

Özelliği açma/kapatma

useFmtOnly özelliği varsayılan olarak kapalıdır. Kullanıcılar, useFmtOnly=true belirterek bağlantı dizesi aracılığıyla bu özelliği etkinleştirebilir. Örneğin: jdbc:sqlserver://<server>:<port>;encrypt=true;databaseName=<databaseName>;user=<user>;password=<password>;useFmtOnly=true;.

Bu özellik aracılığıyla SQLServerDataSourceda kullanılabilir.

SQLServerDataSource ds = new SQLServerDataSource();
ds.setServerName(<server>);
ds.setPortNumber(<port>);
ds.setDatabaseName("<databaseName>");
ds.setUser("<user>");
ds.setPassword("<password>");
ds.setUseFmtOnly(true);
try (Connection c = ds.getConnection()) {
    // do work with connection
}

Bu özellik, Bildirim düzeyinde de kullanılabilir. Kullanıcılar PreparedStatement.setUseFmtOnly(boolean) özelliğini açabilir/kapatabilir.

Uyarı

Sürücü, Deyim düzeyi özelliğine, Bağlantı düzeyi özelliğinden daha fazla öncelik verecek.

Özelliği kullanma

Etkinleştirildikten sonra, sürücü Parametre Meta Verilerini sorgulamak yerine sp_describe_undeclared_parameters dahili olarak yeni özelliği kullanmaya başlar. Son kullanıcıdan başka işlem yapılması gerekmez.

final String sql = "INSERT INTO #Bar VALUES (?)";
try (Connection c = DriverManager.getConnection(URL, USERNAME, PASSWORD)) {
    try (Statement s = c.createStatement()) {
        s.execute("CREATE TABLE #Bar(c1 int)");
    }
    try (PreparedStatement p1 = c.prepareStatement(sql); PreparedStatement p2 = c.prepareStatement(sql)) {
        ((SQLServerPreparedStatement) p1).setUseFmtOnly(true);
        ParameterMetaData pmd1 = p1.getParameterMetaData();
        System.out.println(pmd1.getParameterTypeName(1)); // prints int
        ParameterMetaData pmd2 = p2.getParameterMetaData(); // throws exception, Invalid object name '#Bar'
    }
}

Uyarı

Özellik yalnızca sorguları destekler SELECT/INSERT/UPDATE/DELETE . Sorgular desteklenen 4 anahtar sözcük veya Ortak Tablo İfadesi'nin ardından desteklenen sorgulardan biriyle başlamalıdır. Ortak Tablo İfadeleri içindeki parametreler desteklenmez.

Bilinen sorunlar

Sql ayrıştırma mantığındaki boşluklardan kaynaklanan özellikle ilgili bazı sorunlar vardır. Bu sorunlar, özelliğin gelecekteki güncelleştirmelerinde giderilebilir ve geçici çözüm önerileriyle birlikte aşağıda belgelenmiştir.

A. Önceden tanımlanmış takma ad kullanma

CREATE TABLE Foo(c1 int)

DELETE fooAlias FROM Foo fooAlias WHERE c1 > ?; --Invalid object name 'fooAlias'

--Workaround #1: Specify AS keyword
DELETE fooAlias FROM Foo AS fooAlias WHERE c1 > ?;
--Workaround #2: Use the table name
DELETE Foo FROM Foo fooAlias WHERE c1 > ?;

B. Tablolarda paylaşılan sütun adları olduğunda belirsiz Sütun Adı

CREATE TABLE Foo(c1 int, c2 int, c3 int)
CREATE TABLE Bar(c1 int, c2 int, c3 int)

SELECT c1,c2 FROM Foo WHERE c3 IN (SELECT c3 FROM Bar WHERE c1 > ? and c2 < ? and c3 = ?); --Ambiguous Column Name

--Workaround: Use aliases
SELECT c1,c2 FROM Foo WHERE c3 IN (SELECT c3 FROM Bar b WHERE b.c1 = ? and b.c2 = ? and b.c3 = ?);

C. Parametreleri olan bir alt sorgudan SELECT


CREATE TABLE Foo(c1 int)

SELECT * FROM (SELECT * FROM Foo WHERE c1 = ?) WHERE c1 = ?; --Incorrect syntax near '?'

--Workaround: N/A

D. SET yan tümcesindeki alt sorgular

CREATE TABLE Foo(c1 int)

UPDATE Foo SET c1 = (SELECT c1 FROM Foo) WHERE c1 = ?; --Incorrect syntax near ')'

--Workaround: Add a 'delimiting' condition
UPDATE Foo SET c1 = (SELECT c1 FROM Foo HAVING (HASH JOIN)) WHERE c1 = ?;

Ayrıca bakınız

Bağlantı özelliklerini ayarlama