Menggunakan parameter bernilai tabel (PHP)

Unduh driver PHP

Berlaku untuk

  • Driver Microsoft 5.10.0 untuk PHP pada SQL Server

Pendahuluan

Anda dapat menggunakan parameter bernilai tabel untuk mengirim beberapa baris data ke pernyataan Transact-SQL atau prosedur tersimpan. Anda tidak perlu membuat tabel sementara. Untuk menggunakan parameter bernilai tabel dengan driver PHP, deklarasikan jenis tabel yang ditentukan pengguna dengan nama, seperti yang ditunjukkan dalam contoh di halaman ini.

Gunakan parameter bernilai tabel dengan prosedur tersimpan

Contoh berikut mengasumsikan tabel, jenis tabel, dan prosedur tersimpan berikut ini ada:

CREATE TABLE TVPOrd(
    OrdNo INTEGER IDENTITY(1,1),
    OrdDate DATETIME,
    CustID VARCHAR(10))


CREATE TABLE TVPItem(
    OrdNo INTEGER,
    ItemNo INTEGER IDENTITY(1,1),
    ProductCode CHAR(10),
    OrderQty INTEGER,
    SalesDate DATE,
    Label NVARCHAR(30),
    Price DECIMAL(5,2),
    Photo VARBINARY(MAX))


--Create TABLE type for use as a TVP
CREATE TYPE TVPParam AS TABLE(
                ProductCode CHAR(10),
                OrderQty INTEGER,
                SalesDate DATE,
                Label NVARCHAR(30),
                Price DECIMAL(5,2),
                Photo VARBINARY(MAX))


--Create procedure with TVP parameters
CREATE PROCEDURE TVPOrderEntry(
        @CustID VARCHAR(10),
        @Items TVPParam READONLY,
        @OrdNo INTEGER OUTPUT,
        @OrdDate DATETIME OUTPUT)
AS
BEGIN
    SET @OrdDate = GETDATE(); SET NOCOUNT ON;
    INSERT INTO TVPOrd (OrdDate, CustID) VALUES (@OrdDate, @CustID);
    SELECT @OrdNo = SCOPE_IDENTITY();
    INSERT INTO TVPItem (OrdNo, ProductCode, OrderQty, SalesDate, Label, Price, Photo)
    SELECT @OrdNo, ProductCode, OrderQty, SalesDate, Label, Price, Photo
    FROM @Items
END

driver PHP menggunakan pengikatan per baris untuk parameter bernilai tabel (TVP), dan Anda harus memberikan nama tipe dalam bentuk string yang tidak kosong. Dalam contoh ini, namanya adalah TVPParam. Input TVP pada dasarnya merupakan pasangan kunci-nilai dengan nama tipe TVP sebagai kunci dan data input sebagai larik bertingkat. Contohnya:

$image1 = fopen($pic1, 'rb');
$image2 = fopen($pic2, 'rb');
$image3 = fopen($pic3, 'rb');

$items = [
    ['0062836700', 367, "2009-03-12", 'AWC Tee Male Shirt', '20.75', $image1],
    ['1250153272', 256, "2017-11-07", 'Superlight Black Bicycle', '998.45', $image2],
    ['1328781505', 260, "2010-03-03", 'Silver Chain for Bikes', '88.98', $image3],
];

// Create a TVP input array
$tvpType = 'TVPParam';
$tvpInput = array($tvpType => $items);

// To execute the stored procedure, either execute a direct query or prepare this query:
$callTVPOrderEntry = "{call TVPOrderEntry(?, ?, ?, ?)}";

Menggunakan driver SQLSRV

Anda dapat memanggil sqlsrv_query atau sqlsrv_prepare dengan sqlsrv_execute. Contoh berikut menunjukkan kasus penggunaan sebelumnya:

$custCode = 'SRV_123';
$ordNo = 0;
$ordDate = null;
$params = array($custCode,
                array($tvpInput, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_TABLE, SQLSRV_SQLTYPE_TABLE), // or simply array($tvpInput),
                array(&$ordNo, SQLSRV_PARAM_OUT),
                array(&$ordDate, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)));
$stmt = sqlsrv_query($conn, $callTVPOrderEntry, $params);
if (!$stmt) {
    print_r(sqlsrv_errors());
}
sqlsrv_next_result($stmt);

Selain itu, Anda dapat menggunakan sqlsrv_send_stream_data untuk mengirim data TVP setelah eksekusi. Contohnya:

$options = array("SendStreamParamsAtExec" => 0);
$stmt = sqlsrv_prepare($conn, $callTVPOrderEntry, $params, $options);
if (!$stmt) {
    print_r(sqlsrv_errors());
}
$res = sqlsrv_execute($stmt);
if (!$res) {
    print_r(sqlsrv_errors());
}

// Now call sqlsrv_send_stream_data in a loop
while (sqlsrv_send_stream_data($stmt)) {
}
sqlsrv_next_result($stmt);

Gunakan driver PDO_SQLSRV

Ini adalah contoh yang setara saat menggunakan driver PDO_SQLSRV. Anda dapat menggunakan persiapan/eksekusi dengan bindParam dan menentukan input TVP sebagai PDO::PARAM_LOB. Jika tidak, Anda akan mendapatkan kesalahan ini: Operand type clash: nvarchar is incompatible with ....

try {
    $stmt = $conn->prepare($callTVPOrderEntry);
    $stmt->bindParam(1, $custCode);
    $stmt->bindParam(2, $tvpInput, PDO::PARAM_LOB);
    // 3 - OrdNo output
    $stmt->bindParam(3, $ordNo, PDO::PARAM_INT, 10);
    // 4 - OrdDate output
    $stmt->bindParam(4, $ordDate, PDO::PARAM_STR, 20);
    $stmt->execute();
} catch (PDOException $e) {
    ...
}

Jika prosedur tersimpan hanya mengambil parameter input, Anda dapat menggunakan bindValue alih-alih bindParam.

Menggunakan skema selain skema dbo default

Jika Anda tidak menggunakan skema dbo default, maka Anda harus memberikan nama skema. Bahkan jika nama skema berisi karakter spasi, jangan gunakan pemisah seperti [ atau ].

    $inputs = [
        ['ABC', 12345, null],
        ['DEF', 6789, 'This is a test']
    ];
    $schema = 'Sales DB';
    $tvpType = 'TestTVP';

    // i.e. the TVP type name is "[Sales DB].[TestTVP]"
    $tvpInput = array($tvpType => $inputs, $schema);

Gunakan parameter bernilai tabel tanpa prosedur tersimpan

Anda dapat menggunakan parameter bernilai tabel tanpa prosedur tersimpan. Pertimbangkan contoh berikut:

CREATE TYPE id_table_type AS TABLE(id INT PRIMARY KEY)

CREATE TABLE test_table (id INT PRIMARY KEY)

Menggunakan driver SQLSRV

Ini adalah contoh saat menggunakan skema yang ditentukan pengguna:

$schema = 'my schema';
$tvpName = 'id_table_type';

$tsql = "INSERT INTO [$schema].[test_table] SELECT * FROM ?";
$params = [
[[$tvpname => [[1], [2], [3]], $schema]],
];

$stmt = sqlsrv_query($conn, $tsql, $params);
if (!$stmt) {
    print_r(sqlsrv_errors());
}
sqlsrv_free_stmt($stmt);

Gunakan driver PDO_SQLSRV

Ini adalah contoh saat menggunakan skema dbo default:

$tsql = "INSERT INTO test_table SELECT * FROM ?";
$tvpInput = array('id_table_type' => [[1], [2], [3]]);

$stmt = $conn->prepare($tsql);
$stmt->bindParam(1, $tvpInput, PDO::PARAM_LOB);
$result = $stmt->execute();