Menggunakan parameter bernilai tabel (PHP)
Berlaku untuk
- Microsoft Drivers 5.10.0 untuk PHP untuk 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.
Menggunakan 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 row-wise untuk parameter bernilai tabel (TVP), dan Anda harus memberikan nama jenis sebagai string yang tidak kosong. Dalam contoh ini, tautannya adalah TVPParam
. Input TVP pada dasarnya adalah pasangan kunci-nilai dengan nama jenis TVP sebagai kunci dan data input sebagai array berlapis. 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 eksekusi posting data TVP. 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);
Menggunakan 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();