AddOn/SQL-ManagmentStudio_Online/index.php aktualisiert

Update SQL-Query for Export in CSV, SQL Create Text, 
Add Password to the SQL-Query for change Action (Delete, Drop, Update) on SQL Server
This commit is contained in:
olinet 2025-08-01 19:07:12 +02:00
parent b3f2900155
commit 21036ae5ec
1 changed files with 368 additions and 9 deletions

View File

@ -7,11 +7,12 @@ error_reporting(E_ALL);
session_start();
/**************** Servername\Instance ****************/
$ServerName = "<SQL Server HOST>, <SQL Port>";
$ServerName = "<MS SQL Server>, <Port>";
$changeDataInSQLPassword = "XXXXX";
/**************** Cathalog\User ****************/
$ConnectionInfo = array( "Database"=>"<Database>",
"UID"=>"<Username>",
"PWD"=>"<Password>",
$ConnectionInfo = array( "Database"=>"...",
"UID"=>"...",
"PWD"=>"...",
"Encrypt"=>false,
"TrustServerCertificate"=>false,
"CharacterSet" => "UTF-8");
@ -94,6 +95,11 @@ function getDatabaseStructureExport($conn, $format = 'json') {
$structure[$table] = $columns;
}
// Ausgabe als JSON
if ($format === 'array') {
return $structure;
}
// Ausgabe als JSON
if ($format === 'json') {
return json_encode($structure, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
@ -129,6 +135,58 @@ function getDatabaseStructureExport($conn, $format = 'json') {
return null;
}
/*
function exportTableData($conn, $table, $output_format = 'json') {
$query = "SELECT * FROM [$table]";
$stmt = sqlsrv_query($conn, $query);
if (!$stmt) {
return json_encode(['error' => sqlsrv_errors()], JSON_PRETTY_PRINT);
}
$data = [];
$insertSQL = '';
// Hol dir die Spaltennamen
$columns = [];
$fieldMeta = sqlsrv_field_metadata($stmt);
foreach ($fieldMeta as $field) {
$columns[] = $field['Name'];
}
// Geh alle Zeilen durch
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
// Für JSON-Export
if ($output_format === 'json') {
foreach ($row as $key => $value) {
if ($value instanceof DateTime) {
$row[$key] = $value->format('Y-m-d H:i:s');
}
}
$data[] = $row;
}
// Für SQL-Export
if ($output_format === 'sql') {
$values = array_map(function ($v) use ($conn) {
if (is_null($v)) return "NULL";
if ($v instanceof DateTime) return "'" . $v->format('Y-m-d H:i:s') . "'";
return "'" . str_replace("'", "''", $v) . "'";
}, array_values($row));
$insertSQL .= "INSERT INTO [$table] (" . implode(", ", $columns) . ") VALUES (" . implode(", ", $values) . ");\n";
}
}
sqlsrv_free_stmt($stmt);
if ($output_format === 'json') {
return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
return $insertSQL;
}
*/
function exportTableData($conn, $table, $output_format = 'json') {
$query = "SELECT * FROM [$table]";
$stmt = sqlsrv_query($conn, $query);
@ -247,13 +305,24 @@ function getTableData($conn, $table) {
return $rows;
}
/*
function executeSQL($conn, $sql) {
$stmt = sqlsrv_query($conn, $sql);
if ($stmt === false) {
return sqlsrv_errors();
}else{
}
sqlsrv_free_stmt($stmt);
return "Query erfolgreich ausgeführt.";
}*/
/*
function executeSQL($conn, $sql, $format = "json") {
$stmt = sqlsrv_query($conn, $sql);
if ($stmt === false) {
return sqlsrv_errors(); // Falls ein Fehler auftritt, gebe die Fehler zurück
} else {
// Überprüfen, ob die Abfrage Ergebnisse liefert (z. B. bei SELECT)
$results = [];
if (strpos(strtoupper($sql), 'SELECT') !== false) {
// Nur bei SELECT-Abfragen die Ergebnisse holen
@ -261,15 +330,155 @@ function executeSQL($conn, $sql) {
$results[] = $row;
}
sqlsrv_free_stmt($stmt);
return $results; // Rückgabe der Ergebnisse der SELECT-Abfrage
if ($format === "csv") {
if (empty($results)) {
return ""; // keine Daten
}
// CSV-String erstellen
$output = "";
// Header-Zeile mit Spaltennamen
$headers = array_keys($results[0]);
$output .= implode(";", $headers) . "\n";
// Datenzeilen
foreach ($results as $row) {
// Werte ggf. mit Anführungszeichen escapen
$escaped = array_map(function($val) {
if ($val === null) return "";
$val = str_replace('"', '""', $val); // Doppelte Quotes für CSV
return '"' . $val . '"';
}, $row);
$output .= implode(";", $escaped) . "\n";
}
return $output;
} else {
// Standard = Array zurückgeben (kann mit json_encode nach JSON gewandelt werden)
return $results;
}
} else {
// Bei INSERT, UPDATE, DELETE etc. die Anzahl der betroffenen Zeilen zurückgeben
$affectedRows = sqlsrv_rows_affected($stmt);
sqlsrv_free_stmt($stmt);
return "Anzahl der betroffenen Zeilen: " . $affectedRows; // Gibt die betroffenen Zeilen zurück
return "Anzahl der betroffenen Zeilen: " . $affectedRows;
}
}
}
*/
function executeSQL($conn, $sql, $format = "json", $admin_pass = null, $realPass="", $exporttableName = "") {
$stmtType = strtoupper(strtok(trim($sql), " ")); // erstes Wort der Query erkennen
// Prüfen ob Query eine Änderung macht
$isWriteQuery = in_array($stmtType, ["INSERT", "UPDATE", "DELETE", "ALTER", "DROP", "CREATE"]);
// Falls Schreib-Query und kein gültiges Passwort => sofort Fehler zurück
if ($isWriteQuery && $admin_pass !== $realPass) {
return ["error" => "Incorrect admin password for write operations."];
}
$stmt = sqlsrv_query($conn, $sql);
if ($stmt === false) {
return sqlsrv_errors(); // Falls ein Fehler auftritt, gebe die Fehler zurück
} else {
$results = [];
if ($stmtType === "SELECT") {
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
$results[] = $row;
}
// === BACKUP_SQL ===
if ($format === "backup_sql") {
$meta = sqlsrv_field_metadata($stmt);
if ($meta === false) {
return "Fehler beim Lesen der Feld-Metadaten.";
}
$create = "CREATE TABLE [$exporttableName] (\n";
$cols = [];
foreach ($meta as $field) {
$colName = $field['Name'];
switch ($field['Type']) {
case SQLSRV_SQLTYPE_INT:
case SQLSRV_SQLTYPE_BIGINT:
case SQLSRV_SQLTYPE_SMALLINT:
$colType = "INT";
break;
case SQLSRV_SQLTYPE_BIT:
$colType = "BIT";
break;
case SQLSRV_SQLTYPE_FLOAT:
case SQLSRV_SQLTYPE_REAL:
$colType = "FLOAT";
break;
case SQLSRV_SQLTYPE_DATETIME:
case SQLSRV_SQLTYPE_DATETIME2:
case SQLSRV_SQLTYPE_DATE:
$colType = "DATETIME";
break;
default:
$colType = "NVARCHAR(MAX)";
break;
}
$cols[] = " [$colName] $colType";
}
$create .= implode(",\n", $cols) . "\n);\n\n";
$inserts = "";
foreach ($results as $row) {
$values = [];
foreach ($row as $val) {
if ($val === null) {
$values[] = "NULL";
} elseif (is_numeric($val)) {
$values[] = $val;
} elseif ($val instanceof DateTime) {
$values[] = "'" . $val->format("Y-m-d H:i:s") . "'";
} else {
$values[] = "'" . str_replace("'", "''", $val) . "'";
}
}
$inserts .= "INSERT INTO [$exporttableName] VALUES (" . implode(", ", $values) . ");\n";
}
sqlsrv_free_stmt($stmt);
return $create . $inserts;
}
// === CSV ===
if ($format === "csv") {
if (empty($results)) {
return "";
}
$output = "";
$headers = array_keys($results[0]);
$output .= implode(";", $headers) . "\n";
foreach ($results as $row) {
$escaped = array_map(function($val) {
if ($val === null) return "";
$val = str_replace('"', '""', $val);
return '"' . $val . '"';
}, $row);
$output .= implode(";", $escaped) . "\n";
}
sqlsrv_free_stmt($stmt);
return $output;
}
// === Default (Array) ===
sqlsrv_free_stmt($stmt);
return $results;
} else {
// Schreibende Query (hier Passwort schon vorher geprüft)
$affectedRows = sqlsrv_rows_affected($stmt);
sqlsrv_free_stmt($stmt);
return "Anzahl der betroffenen Zeilen: " . $affectedRows;
}
}
}
$tables = getTables($conn);
@ -281,7 +490,13 @@ $tableColumns = $currentTable ? getColumns($conn, $currentTable) : [];
$resultMessage = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['sql_query'])) {
$sqlQuery = $_POST['sql_query'];
$resultMessage = executeSQL($conn, $sqlQuery);
$returnformat = "json";
$adminPass = "";
$exportTabelName = "ExportTable".rand();
if(isset($_POST['format'])){ $returnformat = $_POST['format']; }
if(isset($_POST['admin_pass'])){ $adminPass = $_POST['admin_pass']; }
if(isset($_POST['exporttabelName'])){ $exportTabelName = $_POST['exporttabelName']; }
$resultMessage = executeSQL($conn, $sqlQuery, $returnformat, $adminPass, $changeDataInSQLPassword, $exportTabelName);
}
sqlsrv_close($conn);
@ -307,6 +522,11 @@ sqlsrv_close($conn);
<div id="sidebar">
<h2>Tabellen</h2>
<?php
// $dbStruckture = getDatabaseStructureExport($conn, 'array');
//echo count($dbStruckture);
?>
<ul>
<?php foreach ($tables as $table): ?>
<li><a href="?table=<?= $table ?>"><?= $table ?></a></li>
@ -320,6 +540,27 @@ sqlsrv_close($conn);
<a href="?sql=1">SQL</a>
</div>
<?php /* if ($currentTable): ?>
<h2>Tabelle: <?= htmlspecialchars($currentTable) ?></h2>
<table>
<tr>
<th>#</th> <!-- Neue Spalte für die laufende ID -->
<?php foreach ($tableColumns as $column): ?>
<th><?= htmlspecialchars($column) ?></th>
<?php endforeach; ?>
</tr>
<?php $rowNumber = 1; ?> <!-- Zähler initialisieren -->
<?php foreach ($tableData as $row): ?>
<tr>
<td><?= $rowNumber++; ?></td> <!-- Hochzählende ID einfügen -->
<?php foreach ($tableColumns as $column): ?>
<td><?= htmlspecialchars($row[$column] ?? '') ?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</table>
<?php endif; */ ?>
<?php if ($currentTable): ?>
<h2>Tabelle: <?= htmlspecialchars($currentTable) ?></h2>
<table id="data-table">
@ -373,10 +614,128 @@ sqlsrv_close($conn);
</script>
<?php endif; ?>
<?php /* if ($currentTable): ?>
<h2>Tabelle: <?= htmlspecialchars($currentTable) ?></h2>
<div id="table-container">
<table id="data-table">
<thead>
<tr>
<th>#</th>
<?php foreach ($tableColumns as $column): ?>
<th><?= htmlspecialchars($column) ?></th>
<?php endforeach; ?>
</tr>
<tr>
<th></th> <!-- Platzhalter für die ID-Spalte -->
<?php foreach ($tableColumns as $column): ?>
<th><input type="text" class="column-filter" placeholder="Filtern..."></th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php $rowNumber = 1; ?>
<?php foreach ($tableData as $row): ?>
<tr>
<td><?= $rowNumber++; ?></td>
<?php foreach ($tableColumns as $column): ?>
<td><?= htmlspecialchars($row[$column] ?? '') ?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div id="pagination-controls"></div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const rowsPerPage = 250; // Anzahl der Zeilen pro Seite
const table = document.getElementById('data-table');
const tbody = table.querySelector('tbody');
const rows = Array.from(tbody.querySelectorAll('tr'));
const paginationControls = document.getElementById('pagination-controls');
let currentPage = 1;
let filteredRows = rows;
function renderTable() {
const start = (currentPage - 1) * rowsPerPage;
const end = start + rowsPerPage;
rows.forEach((row, index) => {
row.style.display = index >= start && index < end ? '' : 'none';
});
renderPaginationControls();
}
function renderPaginationControls() {
paginationControls.innerHTML = '';
const totalPages = Math.ceil(filteredRows.length / rowsPerPage);
for (let i = 1; i <= totalPages; i++) {
const button = document.createElement('button');
button.textContent = i;
button.classList.add('pagination-button');
if (i === currentPage) button.classList.add('active');
button.addEventListener('click', () => {
currentPage = i;
renderTable();
});
paginationControls.appendChild(button);
}
}
// Filterung
const filters = document.querySelectorAll('.column-filter');
filters.forEach((filter, index) => {
filter.addEventListener('input', function () {
const filterValue = this.value.toLowerCase();
filteredRows = rows.filter(row => {
const cell = row.cells[index + 1]; // +1 wegen der ID-Spalte
if (cell) {
const cellText = cell.textContent.toLowerCase();
return cellText.includes(filterValue);
}
return false;
});
currentPage = 1;
renderTable();
});
});
renderTable();
});
</script>
<style>
.pagination-button {
margin: 5px;
padding: 5px 10px;
cursor: pointer;
}
.pagination-button.active {
background-color: #007bff;
color: white;
border: none;
}
</style>
<?php endif; */ ?>
<?php if (isset($_GET['sql'])): ?>
<h2>SQL Query Executor</h2>
<form method="post">
<textarea name="sql_query" placeholder="Gib dein SQL-Statement hier ein..."></textarea><br>
<textarea name="sql_query" placeholder="Gib dein SQL-Statement hier ein..."><?php if (isset($_POST['sql_query'])){ echo $_POST['sql_query']; } ?></textarea><br>
<select name="format">
<option value="json">JSON </option>
<option value="csv">csv</option>
<option value="backup_sql">Backup Table and Data</option>
</select>
<input type="password" name="admin_pass" placeholder="Admin Password"/>
<input type="text" name="exporttabelName" placeholder="Export Tablename" />
<button type="submit">SQL ausführen</button>
</form>