Compare commits
11 Commits
be1a93e042
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 9eeea3eed1 | |||
| 8ddd29a1fc | |||
| f7265676a8 | |||
| eec5516e14 | |||
| 488426b1aa | |||
| 5776bad6b6 | |||
| 6c45705611 | |||
| 4bb39bcc51 | |||
| cc6ed5796e | |||
| 4dde3b8f38 | |||
| d6a59d427f |
@@ -0,0 +1,5 @@
|
||||
# Variable Schichthöhen
|
||||
Dieses Symbol ist beim Slicer beim Markieren des Objektes verfügbar. Man kann Radius etc. beeinflussen
|
||||
|
||||
# Error zu viele Ladefehler am Prusa
|
||||
Einstellungen Hardware Druckkopf Nextruder Wartung
|
||||
@@ -188,3 +188,35 @@ https://www.youtube.com/watch?v=N3U2noAHgBo&t=88s
|
||||
|
||||
Preferences --> Themes --> 3D View
|
||||
|
||||
## Mesh zu Curve
|
||||
|
||||
1. in Objektmodus
|
||||
2. Object --> Convert --> Curve
|
||||
|
||||
## Curve neu berechnen z. B. auf 64 Vertices
|
||||
|
||||
1. Curve auswählen
|
||||
2. Add --> Modifier --> Geometry Nodes
|
||||
3. Anwählen Geometry Nodes
|
||||
4. Shift A --> Search: Resample
|
||||
5. Auf 64 Vertices stellen
|
||||
|
||||
Spiegeln von Objekten
|
||||
|
||||
Markieren und Add Mirror
|
||||
|
||||
# Tests
|
||||
|
||||
## Trennen eines Meshs
|
||||
|
||||
P auf zwei Ringe
|
||||
|
||||
Löschen der Edges zwischen den Ringen
|
||||
|
||||
## Zusammensetzen
|
||||
|
||||
Beide Meshes im Object-Mode auswählen
|
||||
|
||||
cmd j
|
||||
|
||||
Beide Meshes markieren, Edge --> Bridge Edge Loops
|
||||
|
||||
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 51 KiB |
@@ -1,11 +1,22 @@
|
||||
# MAC
|
||||
|
||||
Kontrolle Filesystem
|
||||
## Kontrolle Filesystem
|
||||
|
||||
diskutil info "/Volumes/NO NAME"
|
||||
|
||||
SCP
|
||||
## SCP
|
||||
|
||||
Beim Transport von Files zum MAC kann es Probleme geben, daher
|
||||
|
||||
alias scp='noglob scp'
|
||||
alias scp='noglob scp'
|
||||
|
||||
## Rechte des externen Filesystems
|
||||
|
||||
Normalerweise ignoriert das OS das Setzen der Rechte auf externen Filesystemen, d.h. es wird nur Standard gesetzt. Um dies zu korrigieren muss man
|
||||
|
||||
1. prüfen
|
||||
diskutil info /Volumes/DeinePlatte
|
||||
2. Ownership aktivieren
|
||||
sudo diskutil enableOwnership /Volumes/DeinePlatte
|
||||
|
||||
eingeben
|
||||
@@ -398,6 +398,264 @@ offset 228 --Skipping the first 228 rows in the result set
|
||||
FETCH NEXT 10 ROWS ONLY;
|
||||
|
||||
|
||||
## Einsortieren
|
||||
#######################################################
|
||||
|
||||
### The AS keyword
|
||||
|
||||
|
||||
|
||||
Klare und beschreibende Spaltennamen sind essenziell, um Daten auf sinnvolle Weise darzustellen. Wenn Sie eine Tabelle mit schlechten Spaltennamen zeigen, wird es für Ihr Publikum schwer sein zu verstehen, wovon Sie sprechen.
|
||||
|
||||
Um Spaltennamen zu ändern, können Sie das AS-Schlüsselwort verwenden.
|
||||
|
||||
SELECT col1 AS firstColumn, col2 AS secondColumn, ...
|
||||
FROM table1
|
||||
|
||||
|
||||
######################################################
|
||||
|
||||
## The LIKE keyword
|
||||
|
||||
|
||||
|
||||
Das LIKE-Schlüsselwort wird verwendet, um Ähnlichkeiten von Zeichenketten zu prüfen. Beispielsweise, wenn wir alle Datensätze abrufen möchten, deren Name mit dem Buchstaben a beginnt, dann verwenden wir das LIKE-Schlüsselwort.
|
||||
|
||||
Zwei Hauptwildcards werden verwendet:
|
||||
|
||||
% - steht für eine beliebige Anzahl von Zeichen
|
||||
_ - steht für genau ein Zeichen
|
||||
Zum Beispiel:
|
||||
|
||||
%a - bedeutet jede Zeichenkette, die mit a endet
|
||||
a% - bedeutet jede Zeichenkette, die mit a beginnt
|
||||
%a% - bedeutet jeder String, der a enthält
|
||||
_a% - bedeutet, dass der Buchstabe a der zweite Buchstabe im String ist
|
||||
%a__ - bedeutet, dass der String a an der drittletzten Stelle enthält
|
||||
Um es zu verwenden, schreiben wir:
|
||||
|
||||
SELECT col1, col2, ...
|
||||
FROM table1
|
||||
WHERE col1 LIKE '%a__'
|
||||
|
||||
|
||||
######################################################
|
||||
|
||||
To change column names use the AS keyword:
|
||||
|
||||
SELECT col1 AS firstColumn, col2 AS secondColumn
|
||||
FROM table1
|
||||
The LIKE keyword is used to check string similarities with wildcards:
|
||||
|
||||
% - means any number of characters
|
||||
_ - means exactly one character
|
||||
Common patterns:
|
||||
|
||||
%a - ends with a
|
||||
a% - starts with a
|
||||
%a% - contains a
|
||||
_a% - a is the second character
|
||||
%a__ - a is in the 3rd from last place
|
||||
SELECT col1, col2, ...
|
||||
FROM table1
|
||||
WHERE col1 LIKE '%a__'
|
||||
The BETWEEN operator provides a cleaner way to specify ranges instead of using >= and <=:
|
||||
|
||||
WHERE col1 BETWEEN 5 AND 10
|
||||
This is equivalent to:
|
||||
|
||||
WHERE col1 >= 5 AND col1 <= 10
|
||||
The BETWEEN operator is inclusive, meaning it includes the boundary values in the results.
|
||||
|
||||
Use IN to check if a column matches any value from a list:
|
||||
|
||||
SELECT *
|
||||
FROM table1
|
||||
WHERE col1 IN ('a', 'b', 'c', 'd', 'e', 'f')
|
||||
This is equivalent to multiple OR conditions but much shorter.
|
||||
|
||||
To limit the number of records returned by a query, use the LIMIT keyword:
|
||||
|
||||
SELECT *
|
||||
FROM table1
|
||||
LIMIT 10
|
||||
This returns the top 10 records from the table.
|
||||
|
||||
You can sort data by multiple columns using ORDER BY. The first column specified takes priority, and subsequent columns are used as tie-breakers:
|
||||
|
||||
SELECT *
|
||||
FROM competition
|
||||
ORDER BY age DESC, avg_speed DESC
|
||||
This will:
|
||||
|
||||
First sort by age in descending order
|
||||
If records have the same age, then sort by avg_speed in descending order
|
||||
Use ORDER BY to sort query results. By default, it sorts in ascending order:
|
||||
|
||||
SELECT *
|
||||
FROM table_name
|
||||
ORDER BY column_name
|
||||
To specify sort direction, add ASC (ascending) or DESC (descending):
|
||||
|
||||
ORDER BY column_name DESC
|
||||
ORDER BY column_name ASC
|
||||
Use IS NULL and IS NOT NULL to filter records based on missing values:
|
||||
|
||||
SELECT *
|
||||
FROM table1
|
||||
WHERE col1 IS NULL
|
||||
SELECT *
|
||||
FROM table1
|
||||
WHERE col1 IS NOT NULL
|
||||
Boolean is a data type with two possible values: TRUE or FALSE.
|
||||
|
||||
Examples:
|
||||
|
||||
10 > 100 - FALSE
|
||||
10 > 5 - TRUE
|
||||
10 > 5 AND 100 < 5 - FALSE
|
||||
Internally, TRUE is represented as 1 and FALSE is represented as 0.
|
||||
|
||||
To filter data using booleans, use IS TRUE or IS NOT TRUE keywords:
|
||||
|
||||
SELECT *
|
||||
FROM table1
|
||||
WHERE col1 IS NOT FALSE AND col2 IS TRUE
|
||||
Use parentheses to control the order of operations when combining multiple conditions with AND and OR:
|
||||
|
||||
WHERE age < 30 OR gender = 'female' AND age > 20
|
||||
Returns all people under 30 (any gender) plus all females over 20.
|
||||
|
||||
WHERE (age < 30 OR gender = 'female') AND age > 20
|
||||
Returns only people over 20 who are either under 30 or female.
|
||||
|
||||
Use AND, OR, and NOT keywords to create complex conditions in SQL queries:
|
||||
|
||||
SELECT col1, col2
|
||||
FROM table1
|
||||
WHERE condition1 AND condition2 OR condition3
|
||||
You can stack as many conditions as needed together using these logical operators.
|
||||
|
||||
The NOT keyword is used to negate a condition, meaning we don't want the condition to be met.
|
||||
|
||||
SELECT *
|
||||
FROM people
|
||||
WHERE NOT gender = 'male'
|
||||
The NOT keyword flips the condition. These queries are equivalent:
|
||||
|
||||
WHERE age > 20
|
||||
WHERE NOT age <= 20
|
||||
The OR keyword returns records where at least one condition is true:
|
||||
|
||||
SELECT *
|
||||
FROM people
|
||||
WHERE gender = 'female' OR age < 20
|
||||
Returns rows where gender = 'female' or age < 20 (or both).
|
||||
|
||||
The AND keyword requires both conditions to be true:
|
||||
|
||||
SELECT *
|
||||
FROM people
|
||||
WHERE gender = "female" AND age < 20
|
||||
This returns records where the person is female AND under 20 years old.
|
||||
|
||||
Use the WHERE keyword to add conditions to your SQL queries:
|
||||
|
||||
SELECT * FROM table_name
|
||||
WHERE column_name = 'value'
|
||||
For numeric comparisons:
|
||||
|
||||
SELECT * FROM table_name
|
||||
WHERE column_name <= 20
|
||||
Common comparison operators: =, <, >, <=, >=
|
||||
|
||||
Use DISTINCT to get unique values from a column:
|
||||
|
||||
SELECT DISTINCT column_name FROM table_name
|
||||
Without DISTINCT, duplicate values will be returned. With DISTINCT, each unique value appears only once in the result.
|
||||
|
||||
In databases, rows are called records and columns are called fields.
|
||||
|
||||
Use the asterisk * symbol to select all columns from a table:
|
||||
|
||||
SELECT * FROM table_name
|
||||
Databases store data in organized tables with columns and rows. SQL (Structured Query Language) is used to manage and manipulate data in databases.
|
||||
|
||||
To extract data from a database table, use the SELECT statement with the FROM clause:
|
||||
|
||||
SELECT column1, column2, column3 FROM table_name
|
||||
|
||||
#####################################################
|
||||
|
||||
|
||||
## Mathematical Columns
|
||||
|
||||
|
||||
|
||||
### Verfügbare Tabellen und Spalten:
|
||||
|
||||
products: id, price, quantity
|
||||
Erstellen Sie eine Abfrage, die Folgendes berechnet:
|
||||
|
||||
1. Eine Spalte namens total_value, die den Preis mit der Menge multipliziert und eine feste Versandpauschale von 15 hinzufügt
|
||||
2. Eine Spalte namens discounted_value, die:
|
||||
- Zuerst den Preis mit der Menge multipliziert
|
||||
- Dann einen 20%-Rabatt anwendet (multipliziert mit 0.8)
|
||||
- Schließlich eine feste Versandpauschale von 10 hinzufügt
|
||||
|
||||
Versuchen Sie, Klammern angemessen zu verwenden, um sicherzustellen, dass die Berechnungen in der richtigen Reihenfolge durchgeführt werden!
|
||||
|
||||
select (price * quantity + 15) as total_value, (price * quantity * 0.8 + 10) as discounted_value from products
|
||||
|
||||
|
||||
## The Modulo Operation
|
||||
|
||||
Der Modulo-Operator % gibt den Rest an, der nach der Division einer Zahl durch eine andere übrig bleibt.
|
||||
|
||||
dividend % divisor
|
||||
dividend: Die Zahl, die geteilt wird.
|
||||
divisor: Die Zahl, durch die der Dividend geteilt wird.
|
||||
Zum Beispiel
|
||||
|
||||
10 % 3
|
||||
Hier wird 10 durch 3 geteilt. Die 3 passt dreimal in die 10, mit einem Rest von 1. Daher wird result 1 sein.
|
||||
|
||||
Normalerweise wird Modulo verwendet, um zu prüfen, ob eine Zahl gerade oder ungerade ist:
|
||||
|
||||
Wenn eine Zahl gerade ist, lässt die Division durch 2 einen Rest von 0.
|
||||
Wenn eine Zahl ungerade ist, lässt die Division durch 2 einen Rest von 1.
|
||||
Finden Sie zum Beispiel Zeilen mit geraden Nummern:
|
||||
|
||||
SELECT * FROM table WHERE id % 2 = 0;
|
||||
Oder zum Durchlaufen von Werten:
|
||||
|
||||
number % 12 (gibt 0-11 zurück)
|
||||
number % 8 (gibt 0-7 zurück)
|
||||
Gruppieren Sie zum Beispiel Elemente in 5er-Gruppen:
|
||||
|
||||
SELECT item_number % 5 as group_number FROM inventory;
|
||||
|
||||
|
||||
Welche Abfrage wählt nur ungerade Zeilen aus?
|
||||
SELECT * FROM users WHERE id % 2 = 1;
|
||||
|
||||
Vervollständigen Sie die Abfrage, um Produkte in 4er-Gruppen zu gruppieren:
|
||||
|
||||
SELECT product_id % 4 as group_num FROM products; -- hier wurde nur % hinzugefügt
|
||||
|
||||
|
||||
Welchen Wertebereich kann number % 7 zurückgeben?
|
||||
|
||||
0 through 6
|
||||
|
||||
Der Rest bei der Division durch 7 ist immer kleiner als 7 und reicht von 0 bis 6.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#####################################################
|
||||
|
||||
#### Notizen bei Fehlersuche
|
||||
Hier sollen Werte aus eriner Tabelle in eine andere transferiert werden, jedoch es knallt:
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Übersetzung LaTeX -- Typst
|
||||
https://qwinsi.github.io/tex2typst-webapp/cheat-sheet.html
|
||||
|
||||
# Tabellen
|
||||
|
||||
@@ -45,6 +45,14 @@ löscht Zeilen, die „error“ ODER „warning“ enthalten.
|
||||
:%g/^$/d
|
||||
```
|
||||
|
||||
## Löschen von Leerzeilen
|
||||
|
||||
```
|
||||
:g/^$/d
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Löschen von Leerzeichen/Tabs am Zeileende jeder Zeile
|
||||
````
|
||||
:%s/\s\+$//
|
||||
@@ -157,3 +165,21 @@ a b
|
||||
c d
|
||||
e f
|
||||
```
|
||||
|
||||
## Makros
|
||||
|
||||
### Aufzeichnen
|
||||
|
||||
qa
|
||||
|
||||
a ist nur Beispiel
|
||||
|
||||
### Ausführen
|
||||
|
||||
@a
|
||||
|
||||
a ist nur Beispiel
|
||||
|
||||
### Mehrfaches Ausführen
|
||||
|
||||
100@a
|
||||
@@ -0,0 +1,101 @@
|
||||
# Bruno: Session zur i-doit aufbauen
|
||||
|
||||
In Bruno bekommst du eine "Session" über eine Kombination aus **Environment-Variablen** und dem **API-Key-Login von i-doit**. i-doit selbst nutzt keine klassischen Cookie-Sessions für die JSON-RPC-API, sondern authentifiziert jeden Request per Header – der "Session-Charakter" kommt also über gespeicherte Variablen, die alle Requests teilen.
|
||||
|
||||
## 1. Environment anlegen
|
||||
|
||||
Anlegen eines Environment `demo-idoit` mit:
|
||||
|
||||
```
|
||||
base_url: https://demo.i-doit.com/src/jsonrpc.php
|
||||
apikey: c1ia5q
|
||||
username: admin
|
||||
password: admin
|
||||
```
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
## 2. Login-Request (holt die Session-ID)
|
||||
|
||||
i-doit unterstützt eine echte Session über `idoit.login`. Der Response liefert einen `X-RPC-Auth-Session`-Header, den du für Folge-Requests wiederverwendest.
|
||||
|
||||
**POST** `{{base_url}}`
|
||||
|
||||
Headers:
|
||||
|
||||
```
|
||||
Content-Type: application/json
|
||||
X-RPC-Auth-Username: {{username}}
|
||||
X-RPC-Auth-Password: {{password}}
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
Body (JSON):
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "2.0",
|
||||
"method": "idoit.login",
|
||||
"params": { "apikey": "{{apikey}}" },
|
||||
"id": 1
|
||||
}
|
||||
```
|
||||
|
||||
Im **Script → Post Response** die Session-ID in eine Variable schreiben:
|
||||
|
||||
```javascript
|
||||
bru.setEnvVar("session_id", res.getHeader("x-rpc-auth-session"));
|
||||
```
|
||||
|
||||
## 3. Folge-Requests mit der Session
|
||||
|
||||
Alle weiteren Requests nutzen dann statt Username/Passwort nur noch:
|
||||
|
||||
```
|
||||
Content-Type: application/json
|
||||
X-RPC-Auth-Session: {{session_id}}
|
||||
```
|
||||
|
||||
Body z. B. für eine Objektabfrage:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "2.0",
|
||||
"method": "cmdb.objects.read",
|
||||
"params": { "apikey": "{{apikey}}", "filter": { "type": 5 } },
|
||||
"id": 1
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Logout (optional)
|
||||
|
||||
```json
|
||||
{ "version": "2.0", "method": "idoit.logout", "params": { "apikey": "{{apikey}}" }, "id": 1 }
|
||||
```
|
||||
|
||||
mit Header `X-RPC-Auth-Session: {{session_id}}`.
|
||||
|
||||
---
|
||||
|
||||
**Kernpunkt:** Die Session-ID aus dem Login-Response wird per Post-Response-Script als Environment-Variable gespeichert und von allen Requests im selben Environment geteilt. Damit sparst du dir den Login-Roundtrip pro Abfrage und hast quasi eine durchgehende Session.
|
||||
|
||||
|
||||
#############
|
||||
|
||||
# Stolperstein
|
||||
|
||||
Während der Arbeiten an Bruno ( zu Hause ) bin ich über folgendes Problem gestolpert.
|
||||
Nach dem holen der Session-ID kam immer ein 500er-Fehler. Das lag daran das ich
|
||||
1. die ID geholt habe
|
||||
2. Bruno wohl die Cookies speichert
|
||||
|
||||
Die Cookies kann man in Bruno über die folgenden Punkte ausschalten:
|
||||
1. 
|
||||
2. 
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 72 KiB |
@@ -0,0 +1,160 @@
|
||||
# MySQL Binary Search – Fehlerhafte Zeile automatisch finden
|
||||
|
||||
## Hintergrund
|
||||
|
||||
Bei der Migration von Daten zwischen zwei Tabellen treten gelegentlich Fehler auf. Mit `LIMIT` und `OFFSET` lässt sich der fehlerhafte Bereich manuell eingrenzen – dieser Prozess kann jedoch durch einen Binary-Search-Ansatz vollständig automatisiert werden.
|
||||
|
||||
---
|
||||
|
||||
## Einfaches Skript (SELECT *)
|
||||
|
||||
Für ein simples `SELECT *` ohne komplexe Query:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Konfiguration
|
||||
DB_USER="root"
|
||||
DB_PASS="password"
|
||||
DB_NAME="datenbank"
|
||||
|
||||
SOURCE_TABLE="quelle"
|
||||
TARGET_TABLE="ziel"
|
||||
|
||||
# Gesamtanzahl Zeilen ermitteln
|
||||
TOTAL=$(mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -sNe \
|
||||
"SELECT COUNT(*) FROM $SOURCE_TABLE;")
|
||||
|
||||
echo "Gesamt Zeilen: $TOTAL"
|
||||
|
||||
LOW=0
|
||||
HIGH=$TOTAL
|
||||
|
||||
while [ $((HIGH - LOW)) -gt 1 ]; do
|
||||
MID=$(( (LOW + HIGH) / 2 ))
|
||||
FETCH=$((MID - LOW))
|
||||
|
||||
echo "Teste OFFSET=$LOW LIMIT=$FETCH ..."
|
||||
|
||||
ERROR=$(mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" 2>&1 <<EOF
|
||||
INSERT INTO $TARGET_TABLE
|
||||
SELECT * FROM $SOURCE_TABLE
|
||||
LIMIT $FETCH OFFSET $LOW;
|
||||
EOF
|
||||
)
|
||||
|
||||
if echo "$ERROR" | grep -qi "error"; then
|
||||
HIGH=$MID
|
||||
echo " → Fehler gefunden, eingrenzen bis Zeile $HIGH"
|
||||
else
|
||||
LOW=$MID
|
||||
echo " → OK, weiter ab Zeile $LOW"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "=== Fehlerhafte Zeile gefunden ==="
|
||||
echo "OFFSET: $LOW"
|
||||
mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e \
|
||||
"SELECT * FROM $SOURCE_TABLE LIMIT 1 OFFSET $LOW;"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Erweitertes Skript (komplexe Query mit JOINs, MAX etc.)
|
||||
|
||||
Wenn die Source-Query komplex ist (JOINs, Aggregatfunktionen, GROUP BY), wird sie als Variable definiert und als Subquery genutzt.
|
||||
|
||||
> **Wichtig:** Ein `ORDER BY` ist zwingend erforderlich, damit die Zeilenreihenfolge zwischen den Aufrufen deterministisch bleibt.
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Konfiguration
|
||||
DB_USER="root"
|
||||
DB_PASS="password"
|
||||
DB_NAME="datenbank"
|
||||
|
||||
# Deine Source-Query OHNE LIMIT/OFFSET – als Subquery nutzbar
|
||||
SOURCE_QUERY="SELECT a.id, MAX(b.wert), a.name
|
||||
FROM quelle a
|
||||
JOIN andere b ON a.id = b.ref_id
|
||||
GROUP BY a.id, a.name
|
||||
ORDER BY a.id"
|
||||
|
||||
TARGET_TABLE="ziel"
|
||||
|
||||
# Gesamtanzahl Zeilen der Query ermitteln
|
||||
TOTAL=$(mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -sNe \
|
||||
"SELECT COUNT(*) FROM ($SOURCE_QUERY) AS _count_query;")
|
||||
|
||||
echo "Gesamt Zeilen: $TOTAL"
|
||||
|
||||
LOW=0
|
||||
HIGH=$TOTAL
|
||||
|
||||
while [ $((HIGH - LOW)) -gt 1 ]; do
|
||||
MID=$(( (LOW + HIGH) / 2 ))
|
||||
FETCH=$((MID - LOW))
|
||||
|
||||
echo "Teste OFFSET=$LOW LIMIT=$FETCH ..."
|
||||
|
||||
ERROR=$(mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" 2>&1 <<EOF
|
||||
INSERT INTO $TARGET_TABLE
|
||||
$SOURCE_QUERY
|
||||
LIMIT $FETCH OFFSET $LOW;
|
||||
EOF
|
||||
)
|
||||
|
||||
if echo "$ERROR" | grep -qi "error"; then
|
||||
HIGH=$MID
|
||||
echo " → Fehler, eingrenzen bis Zeile $HIGH"
|
||||
else
|
||||
LOW=$MID
|
||||
echo " → OK, weiter ab Zeile $LOW"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "=== Fehlerhafte Zeile ==="
|
||||
mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e \
|
||||
"$SOURCE_QUERY LIMIT 1 OFFSET $LOW;"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gezielten Wert aus der fehlerhaften Zeile ausgeben
|
||||
|
||||
### Variante 1 – Subquery-Wrapping
|
||||
|
||||
```bash
|
||||
echo "=== Fehlerhafte Zeile ==="
|
||||
mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e \
|
||||
"SELECT a.id, a.name FROM ($SOURCE_QUERY) AS _fehler LIMIT 1 OFFSET $LOW;"
|
||||
```
|
||||
|
||||
### Variante 2 – Direkte Query (empfohlen bei Aggregaten)
|
||||
|
||||
```bash
|
||||
echo "=== Fehlerhafte Zeile – Detailansicht ==="
|
||||
mysql -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e \
|
||||
"SELECT
|
||||
a.id AS 'ID',
|
||||
a.name AS 'Name',
|
||||
MAX(b.wert) AS 'Max-Wert'
|
||||
FROM quelle a
|
||||
JOIN andere b ON a.id = b.ref_id
|
||||
GROUP BY a.id, a.name
|
||||
ORDER BY a.id
|
||||
LIMIT 1 OFFSET $LOW;"
|
||||
```
|
||||
|
||||
Variante 2 ist bei `MAX()` und anderen Aggregatfunktionen übersichtlicher, da die Rohwerte direkt aus der Query kommen und nicht erst durch ein Subquery-Wrapping gehen.
|
||||
|
||||
---
|
||||
|
||||
## Hinweise
|
||||
|
||||
- **ORDER BY** ist Pflicht für deterministische Ergebnisse bei wiederholten Aufrufen.
|
||||
- Die erfolgreichen INSERT-Blöcke bleiben in der Zieltabelle erhalten – bei Bedarf kann jeder Block in eine Transaktion mit `ROLLBACK` bei Fehler gekapselt werden.
|
||||
- Der Binary Search reduziert die Anzahl der Testläufe auf `log₂(n)` – bei 1000 Zeilen also maximal 10 Schritte.
|
||||
@@ -0,0 +1,161 @@
|
||||
# PHP & CSS – Tabellen und Formulare
|
||||
|
||||
## 1. Input-Feld mit vorausgefülltem Wert
|
||||
|
||||
**Problem:** `$value=` ist kein gültiges HTML-Attribut.
|
||||
|
||||
**Lösung:**
|
||||
```html
|
||||
<input name="ls" value="<?= htmlspecialchars($row['ls']) ?>">
|
||||
```
|
||||
|
||||
Doppelte Anführungszeichen außen verwenden, damit die einfachen Anführungszeichen im PHP-Array (`$row['ls']`) nicht kollidieren.
|
||||
|
||||
Weiterer Fehler im Original: doppeltes `</td></td>` und fehlendes schließendes `</td>`.
|
||||
|
||||
**Korrekter Block:**
|
||||
```html
|
||||
<form method="post">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Ticket-Nr.</th>
|
||||
<td><?= htmlspecialchars($row['tt']) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Auftraggeber</th>
|
||||
<td><input name="ls" value="<?= htmlspecialchars($row['ls']) ?>"></td>
|
||||
<th>Bearbeiter</th>
|
||||
<td><?= htmlspecialchars($row['bearbeiter']) ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Spaltenbreite in Tabellen
|
||||
|
||||
### Option 1 – Inline Style
|
||||
```html
|
||||
<th style="width: 150px;">Auftraggeber</th>
|
||||
```
|
||||
|
||||
### Option 2 – CSS-Klasse
|
||||
```css
|
||||
table th { width: 150px; }
|
||||
table th:first-child { width: 100px; }
|
||||
```
|
||||
|
||||
### Option 3 – `<col>`-Element (zentral für jede Spalte)
|
||||
```html
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style="width: 150px;">
|
||||
<col style="width: 250px;">
|
||||
<col style="width: 150px;">
|
||||
<col style="width: 250px;">
|
||||
</colgroup>
|
||||
...
|
||||
</table>
|
||||
```
|
||||
|
||||
> **Wichtig:** `table-layout: fixed` ist erforderlich, damit die Breiten zuverlässig greifen.
|
||||
|
||||
```css
|
||||
table {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Spaltenbreiten zentral für mehrere Tabellen
|
||||
|
||||
Jeder Tabelle eine eigene Klasse geben:
|
||||
|
||||
```html
|
||||
<table class="tabelle-ticket">
|
||||
<table class="tabelle-adressen">
|
||||
```
|
||||
|
||||
CSS in einer zentralen `.css`-Datei:
|
||||
|
||||
```css
|
||||
table {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tabelle-ticket col:nth-child(1) { width: 150px; }
|
||||
.tabelle-ticket col:nth-child(2) { width: 250px; }
|
||||
.tabelle-ticket col:nth-child(3) { width: 150px; }
|
||||
.tabelle-ticket col:nth-child(4) { width: 250px; }
|
||||
|
||||
.tabelle-adressen col:nth-child(1) { width: 100px; }
|
||||
.tabelle-adressen col:nth-child(2) { width: 300px; }
|
||||
```
|
||||
|
||||
Einbinden per:
|
||||
```html
|
||||
<link rel="stylesheet" href="style.css">
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Tabelle ignoriert Spaltenbreiten (Auto-Breite)
|
||||
|
||||
**Ursache:** Fehlendes `table-layout: fixed`.
|
||||
|
||||
```css
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed; /* ← das fehlte */
|
||||
}
|
||||
```
|
||||
|
||||
Außerdem: `max-width: auto` ist ungültig. Entweder weglassen oder konkreten Wert setzen:
|
||||
```css
|
||||
.content {
|
||||
max-width: 1200px; /* oder weglassen */
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Input-Breite sprengt Tabellenlayout
|
||||
|
||||
**Ursache:** `input { width: 100%; }` greift auch auf Inputs in Tabellenzellen.
|
||||
|
||||
**Lösung:** Inputs in Tabellen explizit ausschließen:
|
||||
|
||||
```css
|
||||
/* Inputs nur im Formular-Bereich */
|
||||
.form-bereich input,
|
||||
.form-bereich select {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Inputs in Tabellen zurücksetzen */
|
||||
td input, td select {
|
||||
width: auto;
|
||||
padding: 2px 4px;
|
||||
margin-top: 0;
|
||||
}
|
||||
```
|
||||
|
||||
Oder Formular-Bereich per Klasse kapseln:
|
||||
|
||||
```html
|
||||
<div class="form-bereich">
|
||||
<label>...</label>
|
||||
<input ...>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
... <!-- inputs hier bleiben unberührt -->
|
||||
</table>
|
||||
```
|
||||