As promised, here is a demo of @Cyprien CRUD for SQLite re-written for MSSQL
Demo Flow
[{"id":"aabcc1826b8526ab","type":"subflow","name":"MSSQL-CRUD","info":"Provides CRUD operations for a SQLITE database\r\n\r\n### Dependancies\r\n* node-red-node-sqlite\r\n* @flowfuse/node-red-dashboard\r\n\r\n### Inputs\r\n\r\n: *tableName* (string) : (optional) Override the set table name.\r\n\r\n### Details\r\n\r\nSimple place a CRUD node on your flow, select a database and a page group\r\nand enter the name of the table.\r\n\r\nAt runtime, the selected table can be adjusted bt sending a message\r\nwith a different table name e.g:\r\n\r\n```\r\nmsg.tableName = 'table2'\r\n```\r\n","category":"dashboard 2","in":[{"x":60,"y":60,"wires":[{"id":"74c62b39145e7768"}]}],"out":[{"x":1020,"y":540,"wires":[{"id":"e26ebb252ef3653b","port":0}]},{"x":680,"y":700,"wires":[{"id":"f2dbce3b36de49c8","port":0}]}],"env":[{"name":"group","type":"ui-group","value":"","ui":{"icon":"font-awesome/fa-object-group","label":{"fr":"Group","en-US":"UI Group"},"type":"conf-types"}},{"name":"database","type":"MSSQL-CN","value":"","ui":{"icon":"font-awesome/fa-database","label":{"fr":"sqlite DB","en-US":"Database"},"type":"conf-types"}},{"name":"tableName","type":"str","value":"table1","ui":{"icon":"font-awesome/fa-table","label":{"fr":"Table Name","en-US":"Table"},"type":"input","opts":{"types":["str","env"]}}}],"meta":{"module":"dasboard-2-sqlite-crud","type":"dasboard-2-sqlite-crud","version":"0.2","author":"Cyprien","desc":"A Subflow for CRUD operations on SQL tables","keywords":"sqlite dashboard-2.0","license":"MIT"},"color":"#3FADB5","inputLabels":["Table name"],"icon":"font-awesome/fa-database"},{"id":"36c9f76a7f3ae6b5","type":"ui-template","z":"aabcc1826b8526ab","group":"${group}","page":"","ui":"","name":"MSSQL Table","order":0,"width":0,"height":0,"head":"","format":"<template>\n <v-card flat>\n <template v-slot:text>\n <v-text-field \n v-model=\"search\" \n label=\"Search\" \n prepend-inner-icon=\"mdi-magnify\" \n variant=\"outlined\" \n hide-details\n single-line>\n </v-text-field>\n </template>\n <v-data-table :search=\"search\" :headers=\"headers\" :items=\"items\" :sort-by=\"[{ key: sortBy, order: 'asc' }]\">\n <template v-slot:top>\n <v-toolbar flat>\n <v-toolbar-title>{{ tableName || 'MSSQL CRUD' }}</v-toolbar-title>\n <v-divider class=\"mx-4\" inset vertical></v-divider>\n <v-spacer></v-spacer>\n <v-dialog v-model=\"dialog\" max-width=\"500px\">\n <template v-slot:activator=\"{ props }\">\n <v-btn class=\"mb-2\" color=\"primary\" dark v-bind=\"props\">\n New Item\n </v-btn>\n </template>\n <v-card>\n <v-card-title>\n <span class=\"text-h5\">{{ formTitle }}</span>\n </v-card-title>\n\n <v-card-text>\n <v-container>\n <v-row>\n <v-col v-for=\"header in editableHeaders\" :key=\"header.key\" cols=\"12\" md=\"4\" sm=\"6\">\n <v-text-field v-model=\"editedItem[header.key]\" :label=\"header.title\">\n </v-text-field>\n </v-col>\n </v-row>\n </v-container>\n </v-card-text>\n\n <v-card-actions>\n <v-spacer></v-spacer>\n <v-btn color=\"blue-darken-1\" variant=\"text\" @click=\"close\">\n Cancel\n </v-btn>\n <v-btn color=\"blue-darken-1\" variant=\"text\" @click=\"save\">\n Save\n </v-btn>\n </v-card-actions>\n </v-card>\n </v-dialog>\n <v-dialog v-model=\"dialogDelete\" max-width=\"500px\">\n <v-card>\n <v-card-title class=\"text-h5\">Are you sure you want to delete this item?</v-card-title>\n <v-card-actions>\n <v-spacer></v-spacer>\n <v-btn color=\"blue-darken-1\" variant=\"text\" @click=\"closeDelete\">Cancel</v-btn>\n <v-btn color=\"blue-darken-1\" variant=\"text\" @click=\"deleteItemConfirm\">OK</v-btn>\n <v-spacer></v-spacer>\n </v-card-actions>\n </v-card>\n </v-dialog>\n </v-toolbar>\n </template>\n <template v-slot:item.actions=\"{ item }\">\n <v-icon class=\"me-2\" size=\"small\" @click=\"editItem(item)\">\n mdi-pencil\n </v-icon>\n <v-icon size=\"small\" @click=\"deleteItem(item)\">\n mdi-delete\n </v-icon>\n </template>\n <template v-slot:no-data>\n <v-btn color=\"primary\" @click=\"initialize\">\n Reset\n </v-btn>\n </template>\n </v-data-table>\n </v-card>\n</template>\n\n<script>\n export default {\n data() {\n return {\n search: '',\n dialog: false,\n dialogDelete: false,\n headers: [],\n editableHeaders: [],\n items: [],\n editedIndex: -1,\n editedItem: {},\n defaultItem: {},\n sortBy: '',\n pkColumn: null,\n tableName: '',\n tableInfo: [],\n initialItems: []\n }\n },\n computed: {\n formTitle() {\n return this.editedIndex === -1 ? 'New Item' : 'Edit Item'\n },\n },\n watch: {\n dialog(val) {\n val || this.close()\n },\n dialogDelete(val) {\n val || this.closeDelete()\n },\n // Is it better to use $socket ?\n msg: function () {\n console.log(this.msg.payload)\n this.initialize()\n },\n },\n created() {\n this.initialize()\n },\n methods: {\n initialize() {\n this.tableName = this.msg.tableName\n this.tableInfo = this.msg.payload.pragma\n this.items = this.msg.payload.select\n this.pkColumn = this.tableInfo.find(column => column.pk === 1)\n \n this.headers = this.tableInfo.map(column => ({\n title: column.name,\n key: column.name,\n sortable: true,\n isPk: column.pk === 1\n }))\n this.headers.push({ title: 'Actions', key: 'actions', sortable: false })\n\n this.editableHeaders = this.headers.filter(header => !header.isPk && header.key !== 'actions')\n\n this.defaultItem = this.tableInfo.reduce((acc, column) => {\n if (!column.pk) {\n acc[column.name] = null\n }\n return acc\n }, {})\n\n this.editedItem = { ...this.defaultItem }\n //this.items = [...this.initialItems]\n\n // Set the default sort column (first non-PK column)\n this.sortBy = this.headers.find(header => !header.isPk && header.key !== 'actions')?.key || ''\n },\n editItem(item) {\n this.editedIndex = this.items.indexOf(item)\n this.editedItem = { ...this.defaultItem }\n for (let key in this.defaultItem) {\n this.editedItem[key] = item[key]\n }\n this.dialog = true\n },\n deleteItem(item) {\n this.editedIndex = this.items.indexOf(item)\n this.editedItem = { ...item }\n this.dialogDelete = true\n },\n deleteItemConfirm() {\n console.log(this.editedItem)\n const payload = {\n topic: \"DELETE\",\n tableName: this.tableName,\n payload: {\n id: this.editedItem.id\n }\n };\n this.send(payload)\n this.items.splice(this.editedIndex, 1)\n\n this.closeDelete()\n },\n close() {\n this.dialog = false\n this.$nextTick(() => {\n this.editedItem = { ...this.defaultItem }\n this.editedIndex = -1\n })\n },\n closeDelete() {\n this.dialogDelete = false\n this.$nextTick(() => {\n this.editedItem = { ...this.defaultItem }\n this.editedIndex = -1\n })\n },\n // mounted() {\n // this.$socket.on('msg-input:' + this.id, function(msg) {\n // // do stuff with the message\n // console.log('message received: ' + msg.payload)\n // })\n // },\n save() {\n if (this.editedIndex > -1) {\n // Update existing item\n const updatedItem = { ...this.items[this.editedIndex] }\n for (let key in this.editedItem) {\n updatedItem[key] = this.editedItem[key]\n }\n Object.assign(this.items[this.editedIndex], updatedItem)\n const payload = {\n topic: \"UDPATE\",\n tableName: this.tableName,\n payload: {\n item: updatedItem\n }\n };\n this.send(payload)\n } else {\n // Create new item\n const newItem = { ...this.editedItem }\n if (this.pkColumn) {\n // Generate a temporary ID for the new item\n // In a real application, this would be handled by the backend\n newItem[this.pkColumn.name] = Math.max(0, ...this.items.map(item => item[this.pkColumn.name])) + 1\n }\n this.items.push(newItem)\n const payload = {\n topic: \"INSERT\",\n tableName: this.tableName,\n payload: {\n item: newItem\n }\n };\n this.send(payload)\n }\n this.close()\n },\n },\n}\n</script>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":300,"y":540,"wires":[["9cb600dc1c760da7"]]},{"id":"9cb600dc1c760da7","type":"switch","z":"aabcc1826b8526ab","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"DELETE","vt":"str"},{"t":"eq","v":"UDPATE","vt":"str"},{"t":"eq","v":"INSERT","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":490,"y":540,"wires":[["a6f57055859dc572"],["08e04b7725b3dcc2"],["6ea3c00df1a78442"]]},{"id":"6ea3c00df1a78442","type":"function","z":"aabcc1826b8526ab","name":"INSERT","func":"node.warn({ payload: msg.payload });\nconst data = RED.util.cloneMessage(msg.payload.item);\nconst tableName = msg.tableName\n\n// Extract the ID\nconst id = data.id\ndelete data.id\n\n// Build columns, data placeholders and values array\nconst entries = Object.entries(data)\nconst columns = []\nconst values = []\nconst keys = Object.keys(data)\nfor (let index = 0; index < keys.length; index++) {\n const key = keys[index]\n columns.push('??') // sanitize\n values.push(data[key])\n}\nconst columnsNames = tsqlstring.format(columns.join(', '),keys) \nconst placeHolders = values.map(() => '?').join(', ')\n\n// Construct query using tsqlstring.format to avoid SQLi\nmsg.query = tsqlstring.format(`INSERT INTO ?? (${columnsNames}) \\n VALUES (${placeHolders})`, [tableName, ...values, id])\nmsg.insertQuery = msg.query\nreturn msg\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"tsqlstring","module":"tsqlstring"}],"x":660,"y":580,"wires":[["80b6e275b832aa32"]]},{"id":"a6f57055859dc572","type":"function","z":"aabcc1826b8526ab","name":"DELETE","func":"const tableName = msg.tableName\nmsg.query = tsqlstring.format(`DELETE FROM ?? WHERE id = ?`, [tableName, msg.payload.id])\nmsg.deleteQuery = msg.query\nreturn msg\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"tsqlstring","module":"tsqlstring"}],"x":660,"y":500,"wires":[["80b6e275b832aa32"]]},{"id":"08e04b7725b3dcc2","type":"function","z":"aabcc1826b8526ab","name":"UPDATE","func":"const data = RED.util.cloneMessage(msg.payload.item)\nconst tableName = msg.tableName\n\n// Extract the ID\nconst id = data.id\ndelete data.id\n\n// Build columns, data placeholders and values array\nconst entries = Object.entries(data)\nconst sets = []\nconst values = []\nconst parts = []\nconst keys = Object.keys(data)\nfor (let index = 0; index < keys.length; index++) {\n const key = keys[index]\n parts.push(tsqlstring.format(`?? = ?`, [key, data[key]]))\n}\nconst setWhat = parts.join(', ')\n\n// Construct query\nmsg.query = tsqlstring.format(`UPDATE ?? SET ${setWhat} WHERE id = ?`, [tableName, ...values, id])\nmsg.updateQuery = msg.query\nreturn msg\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"tsqlstring","module":"tsqlstring"}],"x":660,"y":540,"wires":[["80b6e275b832aa32"]]},{"id":"0bc1b70f3b5314e8","type":"link in","z":"aabcc1826b8526ab","name":"link in 1","links":["fe79ed82583fe781"],"x":385,"y":140,"wires":[["36fbf7094b2ada86"]]},{"id":"fe79ed82583fe781","type":"link out","z":"aabcc1826b8526ab","name":"link out 1","mode":"link","links":["0bc1b70f3b5314e8"],"x":1015,"y":500,"wires":[]},{"id":"74c62b39145e7768","type":"switch","z":"aabcc1826b8526ab","name":"has msg.tableName?","property":"tableName","propertyType":"msg","rules":[{"t":"nempty"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":220,"y":40,"wires":[["18d9e09a8d9ccf46"],["47e385f7c0fc866d"]]},{"id":"47e385f7c0fc866d","type":"change","z":"aabcc1826b8526ab","name":"use env tableName","rules":[{"t":"set","p":"tableName","pt":"msg","to":"tableName","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":100,"wires":[["18d9e09a8d9ccf46"]]},{"id":"36fbf7094b2ada86","type":"change","z":"aabcc1826b8526ab","name":"","rules":[{"t":"set","p":"tableName","pt":"msg","to":"tableName","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":100,"wires":[["096ff2bbdaf4399d"]]},{"id":"18d9e09a8d9ccf46","type":"change","z":"aabcc1826b8526ab","name":"","rules":[{"t":"set","p":"tableName","pt":"flow","to":"tableName","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":40,"wires":[["36fbf7094b2ada86"]]},{"id":"096ff2bbdaf4399d","type":"MSSQL","z":"aabcc1826b8526ab","mssqlCN":"4e85bde58681c32a","name":"get identities","outField":"identities","returnType":0,"throwErrors":1,"query":"SELECT \r\n sys.objects.name AS TABLE_NAME, \r\n sys.columns.name AS COLUMN_NAME\r\nFROM sys.columns JOIN sys.objects \r\n ON sys.columns.object_id=sys.objects.object_id\r\nWHERE \r\n sys.columns.is_identity=1\r\n AND\r\n sys.objects.type in (N'U')","modeOpt":"queryMode","modeOptType":"query","queryOpt":"payload","queryOptType":"editor","paramsOpt":"queryParams","paramsOptType":"none","rows":"rows","rowsType":"msg","parseMustache":true,"params":[],"x":190,"y":260,"wires":[["3b13c88ffc3bb01e"]]},{"id":"3b13c88ffc3bb01e","type":"MSSQL","z":"aabcc1826b8526ab","mssqlCN":"4e85bde58681c32a","name":"get primaries","outField":"primaries","returnType":0,"throwErrors":1,"query":"SELECT i.name AS INDEX_NAME,\r\n OBJECT_NAME(ic.OBJECT_ID) AS TABLE_NAME,\r\n COL_NAME(ic.OBJECT_ID,ic.column_id) AS COLUMN_NAME\r\nFROM sys.indexes AS i INNER JOIN \r\n sys.index_columns AS ic ON i.OBJECT_ID = ic.OBJECT_ID\r\n AND i.index_id = ic.index_id\r\nWHERE i.is_primary_key = 1","modeOpt":"queryMode","modeOptType":"query","queryOpt":"payload","queryOptType":"editor","paramsOpt":"queryParams","paramsOptType":"none","rows":"rows","rowsType":"msg","parseMustache":true,"params":[],"x":390,"y":260,"wires":[["6d0bb115eafaf441"]]},{"id":"6d0bb115eafaf441","type":"function","z":"aabcc1826b8526ab","name":"prepare columns sql","func":"let sql = `\nSELECT\n ORDINAL_POSITION as cid,\n COLUMN_NAME as [name], \n DATA_TYPE AS type,\n case when IS_NULLABLE = 'YES' then 0 else 1 end AS notnull,\n COLUMN_DEFAULT as dflt_value,\n *\n FROM INFORMATION_SCHEMA.COLUMNS\n WHERE TABLE_NAME = ?\n`\n\nmsg.columnSelect = tsqlstring.format(sql, [msg.tableName])\nmsg.action = 'pragma';\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"tsqlstring","module":"tsqlstring"}],"x":600,"y":260,"wires":[["7dec8d6bb13118bd"]]},{"id":"7dec8d6bb13118bd","type":"MSSQL","z":"aabcc1826b8526ab","mssqlCN":"4e85bde58681c32a","name":"get columns","outField":"columns","returnType":0,"throwErrors":1,"query":"SELECT i.name AS INDEX_NAME,\r\n OBJECT_NAME(ic.OBJECT_ID) AS TABLE_NAME,\r\n COL_NAME(ic.OBJECT_ID,ic.column_id) AS COLUMN_NAME\r\nFROM sys.indexes AS i INNER JOIN \r\n sys.index_columns AS ic ON i.OBJECT_ID = ic.OBJECT_ID\r\n AND i.index_id = ic.index_id\r\nWHERE i.is_primary_key = 1","modeOpt":"queryMode","modeOptType":"query","queryOpt":"columnSelect","queryOptType":"msg","paramsOpt":"queryParams","paramsOptType":"none","rows":"rows","rowsType":"msg","parseMustache":false,"params":[],"x":810,"y":260,"wires":[["a0e99b62f29489d1"]]},{"id":"a0e99b62f29489d1","type":"function","z":"aabcc1826b8526ab","name":"update pk/identiry","func":"// loop each column, find matching entries in identities and primaries and update\nconst columns = msg.columns || []\nconst primaries = msg.primaries || []\nconst identities = msg.identities || []\n\nfor (let index = 0; index < columns.length; index++) {\n const column = columns[index];\n const primary = primaries.find(e => e.TABLE_NAME === msg.tableName && e.COLUMN_NAME === column.name)\n const identity = identities.find(e => e.TABLE_NAME === msg.tableName && e.COLUMN_NAME === column.name)\n if (primary) {\n column.primary = 1\n }\n if (identity) {\n column.identitiy = 1\n }\n if (column.primary && column.identitiy) {\n column.pk = 1\n }\n}\nmsg.payload = {\n pragma: columns\n}\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":210,"y":400,"wires":[["16c8642501a5240c"]]},{"id":"16c8642501a5240c","type":"function","z":"aabcc1826b8526ab","name":"prepare SELECT","func":"msg.topic = tsqlstring.format('SELECT TOP 100 * FROM ??', [msg.tableName])\nmsg.action = 'select'\nreturn msg\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"tsqlstring","module":"tsqlstring"}],"x":430,"y":400,"wires":[["f7bc781e87da9f8b"]]},{"id":"f7bc781e87da9f8b","type":"MSSQL","z":"aabcc1826b8526ab","mssqlCN":"4e85bde58681c32a","name":"get data","outField":"payload.select","returnType":0,"throwErrors":1,"query":"SELECT i.name AS INDEX_NAME,\r\n OBJECT_NAME(ic.OBJECT_ID) AS TABLE_NAME,\r\n COL_NAME(ic.OBJECT_ID,ic.column_id) AS COLUMN_NAME\r\nFROM sys.indexes AS i INNER JOIN \r\n sys.index_columns AS ic ON i.OBJECT_ID = ic.OBJECT_ID\r\n AND i.index_id = ic.index_id\r\nWHERE i.is_primary_key = 1","modeOpt":"queryMode","modeOptType":"query","queryOpt":"topic","queryOptType":"msg","paramsOpt":"queryParams","paramsOptType":"none","rows":"rows","rowsType":"msg","parseMustache":false,"params":[],"x":620,"y":400,"wires":[["36c9f76a7f3ae6b5"]]},{"id":"e26ebb252ef3653b","type":"MSSQL","z":"aabcc1826b8526ab","mssqlCN":"4e85bde58681c32a","name":"query","outField":"payload.select","returnType":0,"throwErrors":1,"query":"SELECT i.name AS INDEX_NAME,\r\n OBJECT_NAME(ic.OBJECT_ID) AS TABLE_NAME,\r\n COL_NAME(ic.OBJECT_ID,ic.column_id) AS COLUMN_NAME\r\nFROM sys.indexes AS i INNER JOIN \r\n sys.index_columns AS ic ON i.OBJECT_ID = ic.OBJECT_ID\r\n AND i.index_id = ic.index_id\r\nWHERE i.is_primary_key = 1","modeOpt":"queryMode","modeOptType":"query","queryOpt":"query","queryOptType":"msg","paramsOpt":"queryParams","paramsOptType":"none","rows":"rows","rowsType":"msg","parseMustache":false,"params":[],"x":850,"y":540,"wires":[["fe79ed82583fe781"]]},{"id":"f2dbce3b36de49c8","type":"catch","z":"aabcc1826b8526ab","name":"","scope":null,"uncaught":false,"x":550,"y":700,"wires":[[]]},{"id":"80b6e275b832aa32","type":"junction","z":"aabcc1826b8526ab","x":760,"y":540,"wires":[["e26ebb252ef3653b"]]},{"id":"4e85bde58681c32a","type":"MSSQL-CN","tdsVersion":"7_4","name":"","server":"172.29.225.148","port":"1433","encyption":true,"trustServerCertificate":true,"database":"db1","useUTC":true,"connectTimeout":"15000","requestTimeout":"15000","cancelTimeout":"5000","pool":"5","parseJSON":false,"enableArithAbort":true,"readOnlyIntent":false},{"id":"2ff1080d58630657","type":"subflow:aabcc1826b8526ab","z":"953fa035e1275ec2","name":"","env":[{"name":"group","value":"d8d5ce268004b131","type":"conf-type"},{"name":"database","value":"4e85bde58681c32a","type":"conf-type"},{"name":"tableName","value":"Users","type":"str"},{"name":"sqlite","value":"","type":"str"}],"x":1080,"y":400,"wires":[[],["52fe8e3bc1fb9e87"]]},{"id":"1d859d277138d343","type":"ui-dropdown","z":"953fa035e1275ec2","group":"d8d5ce268004b131","name":"","label":"Select a table:","tooltip":"","order":3,"width":"12","height":"1","passthru":true,"multiple":false,"chips":false,"clearable":false,"options":[{"label":"PalletWeights","value":"PalletWeights","type":"str"},{"label":"Users","value":"Users","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":640,"y":400,"wires":[["40d1249d3861acd8","1e110b1f7eabd002"]]},{"id":"6a2258d443142ffe","type":"ui-control","z":"953fa035e1275ec2","name":"","ui":"22ea43815413e748","events":"connect","x":340,"y":480,"wires":[["1b895505162f7e45"]]},{"id":"1b895505162f7e45","type":"change","z":"953fa035e1275ec2","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"mssql_table","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":480,"wires":[["1d859d277138d343"]]},{"id":"40d1249d3861acd8","type":"change","z":"953fa035e1275ec2","name":"","rules":[{"t":"set","p":"mssql_table","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":480,"wires":[[]]},{"id":"1e110b1f7eabd002","type":"change","z":"953fa035e1275ec2","name":"","rules":[{"t":"set","p":"tableName","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":870,"y":400,"wires":[["2ff1080d58630657"]]},{"id":"52fe8e3bc1fb9e87","type":"debug","z":"953fa035e1275ec2","name":"error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1160,"y":480,"wires":[]},{"id":"d8d5ce268004b131","type":"ui-group","name":"MSSQL Crud Demo","page":"1525cc4810388af6","width":"12","height":"1","order":-1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"22ea43815413e748","type":"ui-base","name":"base","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"navigationStyle":"default","titleBarStyle":"default"},{"id":"1525cc4810388af6","type":"ui-page","name":"MSSQL Crud Demo","ui":"22ea43815413e748","path":"/mssql","icon":"home","layout":"grid","theme":"c2ff5ba1f92a0f0e","order":-1,"className":"","visible":"true","disabled":"false"},{"id":"c2ff5ba1f92a0f0e","type":"ui-theme","name":"Default","colors":{"surface":"#ffffff","primary":"#0094ce","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]
NOTES:
- I have made no attempt to extend upon what was achieved in the original taken from here
- data types are not parsed
- input fields are not mapped to proper controls (like time or date widgets)
- Swapped out the
sqlstring
for thetsqlstring
NPM module for MS T-SQL escaping and injection hack prevention