SAP Hana 数据库编程接口 - Node.js

自 SAP HANA SP 11 之后,可以使用 Node.js 作为 Hana 的编程接口。SAP 将 Application server 简称为 XS。现在 XS 已经演化为 Advanced 版本。为了区别,之前的 XS 被称为 XS Classical。

从下图可以看出,和 Hana DB 进行交互的有 HANA XS Classical 、Hana Cloud Platform (HCP) 和 XS Advanced。而能够运行在 HCP 和 XS Advanced 的编程接口包括 XSJS (SAP 推出的服务器端 JavaScript,但目前看,社区并不活跃)、Node.js、Tomcat / TomEE (Java 应用程序编写)等。最近测试了 Node.js 编程接口,感觉还不错。

hdb 模块

Node.js 的编程接口模块是 hdb,可以用 npm install hdb 安装。Github 的源码地址为:node-hdb。有示例和说明,容易学习。

hdb CRUD

本文打算介绍两个方面:

  • hdb CRUD 的基本方法;

  • 以及如何利用 Node.js 的 express 框架实现 REST 风格 API (Restful API)。

先看看基本使用方法:

var hdb = require('hdb')

var client = hdb.createClient({
    host: '192.168.2.100,
    port: 30015,
    user: 'STONE',
    password: 'pwd'
});

client.connect(function(err){
    if (err){
        return console.error('Connect error', err);
    }
    var sql = 'SELECT * FROM STONE.EMP_MASTER';
    client.exec(sql, function(err, rows){
        if (err){
            return console.error('Execute error', err);
        }
        console.log('Results:', rows);
    });
});

和前几篇一样,仍然使用 STONE.EMP_MASTER 作为数据源。我们注意到,Node.js 广泛使用异步回调函数。使用异步的原因是 : Node.js 是单线程的,通过异步来避免阻塞 (blocking)。比如,从Hana 数据库查询 employees 表,但不知道需要多久能获得查询结果,通过异步机制,数据查询到之后放在 rows 中。

上面的 SQL 语句没有参数。下面通过 insert 语句来说明带参数 SQL 语句的处理方法。

client.connect(function(err){
    if (err){
        return console.error('Connect error', err);
    }

    var sql = 'INSERT INTO STONE.EMP_MASTER VALUES(?,?,?,?,?,?,?,?)';

    client.prepare(sql, function(err, statement){
        if (err){
            return console.error('Prepare error:', err);
        }

        var params = ['9001','Male',18,'test4@qq.com','13800-138000','Bachelor','Married',1];

        statement.exec(params, function(err, affectedRows){
            if (err){
                return console.error('Execute error:', err);
            }
            console.log('Affected rows:', affectedRows);
        });
    });
});
  • client.prepare() 先处理语句,成功后放在 statement

  • statement.exec() 语句执行查询,函数的第一个参数是 SQL 语句的参数。注意这个参数是数组类型,即使只有一个参数,也要使用数组。

提供 REST 风格的 Service

使用 Node.js 的 express 框架来实现。网上有非常多使用 express 创建 REST 风格 API 的教程,这里就不细说步骤了。后面会介绍怎样在 OpenUI5 中通过 Rest Service 来对对数据库进行增删改查。

  • 安装 Node.js

  • 创建一个文件夹,在文件夹中运行 npm init 创建 packages.json 文件。

  • 安装 express,这里提供一种方法: npm install express --save--save 参数会修改 packages.json 文件。

  • 安装 body-parser。这个模块将处理 post 请求,对 post 请求进行解析。

工程的文件结构如下:

主要文件有:

  • server.js : 启动服务
  • dbconfig.js: hana 数据库连接的配置信息
  • emp.controller.js: emp_master 表增删改查
  • emp_routes.js: 路由管理

先说明 package.json 文件,管理 app 依赖的模块:

{
  "name": "hana_app",
  "version": "1.0.0",
  "description": "hana in nodejs + express",
  "main": "server.js",
  "dependencies": {
    "body-parser": "^1.18.2",
    "express": "^4.16.2",
    "hdb": "^0.15.2"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Stone Wang",
  "license": "MIT"
}

server.js

var express = require('express');
var bodyParser = require('body-parser');

var app = express();

// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: true}));

// parse requests of content-type - application/json
app.use(bodyParser.json());

// home page
app.get('/', function(req, res){
    res.json('Welcome.');
});

// register routes
var route = require('./app/routes/emp.routes.js')
route(app);

// listen on port 3000
app.listen(3000, function(){
    console.log('Server is running on port 3000.');
});

server.js 中定义首页的响应,注册路由以及侦听 3000 端口。

dbconfig.js

保存数据库的配置信息,是一个对象:

module.exports = {
    hana:{
        host: '192.168.2.100',
        port: 30015,
        user: 'STONE',
        password: 'pwd'
    }
};

emp.controller.js

var hdb = require("hdb");
var dbconfig = require("../../config/dbconfig.js");

var client = hdb.createClient(dbconfig.hana);

// list all
exports.listAll = function(req, res){
    var sql = "SELECT * FROM STONE.EMP_MASTER";

    client.connect(function(err){
        if (err){
            res.send({"error": err.message});
        }
        client.exec(sql, function(err, rows){
            if (err){
                res.send({"error": err.message});
            }
            client.end();
            res.send({rows});
        });
    })
};

// query by id
exports.queryById = function(req, res){
    var sql = "SELECT * FROM STONE.EMP_MASTER WHERE EMP_ID=?";
    client.connect(function(err){
        if (err){
            res.send({"error": err.message});
        }
        client.prepare(sql, function(err, statement){
            if (err){
                res.send({"error": err.message});
            }
            statement.exec([req.params.emp_id], function(err, rows){
                if (err){
                    res.send({"error": err.message});
                }
                client.end();
                res.send({rows});
            });
        });
    });
};

// create
exports.create = function(req, res){
    var sql = "INSERT INTO STONE.EMP_MASTER VALUES(?,?,?,?,?,?,?,?)";
    client.connect(function(err){
        if (err){
            res.send({"error": err.message});
        }
        client.prepare(sql, function(err, statement){
            if (err){
                res.send({"error": err.message});
            }

            var params = [
                req.body.EMP_ID,
                req.body.GENDER,
                req.body.AGE,
                req.body.EMAIL,
                req.body.PHONE_NR,
                req.body.EDUCATION,
                req.body.MARITAL_STAT,
                req.body.NR_OF_CHILDREN
            ];
            statement.exec(params, function(err, data){
                if (err){
                    res.send({"error": err.message});
                }
                client.end();
                res.sendStatus(200);
            });
        });
    });
};

// update
exports.update = function(req, res){
    var sql = "UPDATE STONE.EMP_MASTER SET GENDER=?, AGE=?, EMAIL=?, PHONE_NR=?, EDUCATION=?, MARITAL_STAT=?, NR_OF_CHILDREN=? WHERE EMP_ID=?";
    client.connect(function(err){
        if (err){
            res.send({"error": err.message});
        }
        client.prepare(sql, function(err, statement){
            if (err){
                res.send({"error": err.message});
            }

            var params = [       
                req.body.GENDER,
                req.body.AGE,
                req.body.EMAIL,
                req.body.PHONE_NR,
                req.body.EDUCATION,
                req.body.MARITAL_STAT,
                req.body.NR_OF_CHILDREN,
                req.params.emp_id
            ];

            statement.exec(params, function(err, data){
                if (err){
                    res.send({"error": err.message});
                }
                client.end();
                res.sendStatus(200);
            });
        });
    });
};

// delete
exports.delete = function(req, res){
    var sql = "DELETE FROM STONE.EMP_MASTER WHERE EMP_ID=?";
    client.connect(function(err){
        if (err){
            res.send({"error": err.message});
        }
        client.prepare(sql, function(err, statement){
            if (err){
                res.send({"error": err.message});
            }

            statement.exec([req.params.emp_id], function(err, data){
                if (err){
                    res.send({"error": err.message});
                }
                client.end();
                res.sendStatus(200);
            });
        });
    });
};

emp.routes.js

module.exports = function(app){
    var empController = require("../controllers/emp.controller.js");

    // list all
    app.get('/employees', empController.listAll);

    // query by ID
    app.get('/employee/:emp_id', empController.queryById);

    // create
    app.post('/employee/create', empController.create);

    // update
    app.put('/employee/:emp_id',empController.update);

    // delete
    app.delete('/employee/:emp_id', empController.delete);
};

使用 Postman 测试

在项目文件下,通过 node server.js 启动服务。然后打开 Postman 进行测试。以下是部分截图。

  • listAll

  • create

  • update

  • delete

### 回答1: 《SAP HANA数据库SQL参考手册.doc》是一份详细的SQL参考手册,它提供了在SAP HANA数据库中使用SQL语言进行查询、操作和管理的相关信息和指导。 这个手册主要包含了SQL语法的基本知识,例如如何创建表、插入数据、查询数据、更新数据和删除数据等。它还包括了SQL函数和操作符的详细说明,使用户能够更好地理解和使用这些功能。 此外,参考手册还介绍了如何使用索引和视图进行数据操作和查询优化。它还提供了有关数据类型、约束和事务处理等重要概念的详细说明,帮助用户了解和正确使用这些功能。 这个手册也包含了一些高级的SQL功能,例如存储过程、触发器和用户定义函数等。它解释了如何编写和执行这些高级功能,以及如何处理异常和错误。 总的来说,SAP HANA数据库SQL参考手册是一个全面、系统和易于理解的SQL参考工具,提供了使用SAP HANA数据库进行数据查询、操作和管理的重要知识和指导。无论是新手还是有经验的用户,都可以从中获得帮助,更好地使用和掌握SAP HANA数据库。 ### 回答2: SAP HANA数据库SQL参考手册.doc是一份关于SAP HANA数据库的SQL参考手册的文档。该手册提供了关于SAP HANA数据库中可用的SQL命令和语法的详细说明和示例。 在SAP HANA数据库中,SQL是主要的查询语言,被用于存储、管理和检索数据。SQL参考手册介绍了如何使用SQL来创建表、插入数据、更新数据和删除数据等基本操作,同时也提供了更高级的查询和分析功能的使用方法。 手册中的内容通常包括以下几个部分: 1. 数据类型:手册提供了SAP HANA数据库支持的数据类型列表,包括数字、字符串、日期等。每种数据类型都有详细的说明,指导用户在数据库中正确地存储和处理不同类型的数据。 2. 数据库对象:手册介绍了如何创建和管理数据库对象,例如表、视图和存储过程等。用户可以了解如何使用SQL命令来创建和操作这些对象,以及如何利用它们来组织和管理数据。 3. 查询语句:手册提供了丰富的查询语句示例,包括基本的SELECT语句、连接表、子查询和聚合函数等。用户可以学习如何构建复杂的查询语句来从数据库中检索所需的数据,并了解如何使用聚合函数对数据进行汇总和计算。 4. 数据更新和删除:手册介绍了如何使用SQL命令来更新和删除数据库中的数据。用户可以学习如何使用UPDATE和DELETE语句来修改和删除特定行或列的数据,以及如何使用事务处理来保证数据的一致性和完整性。 总之,SAP HANA数据库SQL参考手册.doc是一份非常有用的文档,它为用户提供了关于SAP HANA数据库中SQL命令和语法的详细说明和示例。用户可以通过学习该手册来掌握SAP HANA数据库的基本操作和高级查询功能,提升对数据库的理解和应用能力。 ### 回答3: "SAP HANA数据库SQL参考手册.doc" 是一个为SAP HANA数据库编写的SQL参考手册文档。SAP HANA是一种内存数据库解决方案,旨在提供实时分析和实时应用程序开发的性能。 该手册对SAP HANA数据库的SQL语言和功能进行了详细的介绍和解释。它包含了SQL查询、DDL(数据定义语言)、DML(数据操作语言)、数据类型、数据函数等方面的内容。 在SQL查询方面,手册提供了各种查询语句的示例和用法,包括选择查询、连接查询、过滤查询等。它还介绍了如何使用SQL进行条件过滤、排序和分组。 在DDL方面,手册解释了如何创建和管理表、视图、索引和用户定义的函数等数据库对象。它还提供了DDL语句的语法和使用示例。 在DML方面,手册介绍了如何通过SQL语句执行数据插入、更新和删除操作。它还包括事务处理和并发控制的相关内容。 此外,手册还提供了丰富的数据类型信息,包括数值类型、日期和时间类型、字符串类型等。它还介绍了可用的数据函数,如聚合函数、数学函数和字符串函数。 "SAP HANA数据库SQL参考手册.doc" 是SAP HANA数据库开发人员和管理员的重要工具,可以帮助他们更轻松地编写和管理数据库中的SQL语句。它提供了详细的文档和示例,使用户能够充分利用SAP HANA数据库的功能和性能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值